Initial commit of main compiler sources (or should I say ... SAUCES!)

This commit is contained in:
2025-06-08 23:58:21 +10:00
parent 60c566025c
commit 06f2613083
214 changed files with 22210 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
package slangc.sdk;
import slangc.parser.Source;
public class ArgsLoader {
public static String[] remove(String[] array, int index) {
if (index < 0 || index >= array.length) {
return array;
}
if (array.length == 1) {
return new String[0];
}
String[] a = new String[array.length - 1];
for (int i = 0; i < a.length; i++) {
if (i < index) {
a[i] = array[i];
} else {
a[i] = array[i + 1];
}
}
return a;
}
public static String[] insert(String[] array, int index, String[] values) {
String[] a = new String[array.length + values.length];
for (int i = 0; i < a.length; i++) {
if (i < index) {
a[i] = array[i];
} else if (i < index + values.length) {
a[i] = values[i - index];
} else {
a[i] = array[i - values.length];
}
}
return a;
}
public static String[] loadArgs(Source source) {
int i = 0;
int lastStart = -1;
int count = 0;
String[] result = new String[0];
while (source.isIndexWithinBounds(i)) {
int c = source.getCharacter(i);
String str = String.construct(new int[]{c});
//Log.line("Reading new character '" + str + "'");
if (c == '\n' || c == ' ' || c == '\r' || c == '\f' || c == '\t' || c == '\n') {
//Log.line("Is separator");
if (lastStart >= 0) {
result = innerAppend(result, source, lastStart, count);
//Log.line("Loaded arg '" + result[result.length-1] + "'");
}
lastStart = -1;
count = 0;
} else {
//Log.line("Is not separator");
if (lastStart < 0) {
lastStart = i;
}
count++;
}
i = source.getNextIndex(i);
}
result = innerAppend(result, source, lastStart, count);
//Log.line("Loaded arg '" + result[result.length-1] + "'");
return result;
}
private static String[] innerAppend(String[] result, Source source, int lastStart, int count) {
if (count > 0) {
result = insert(result, result.length, new String[] {source.getString(lastStart, count)});
}
return result;
}
}

View File

@@ -0,0 +1,482 @@
package slangc.sdk;
import slangc.streams.FileInput;
import slangc.streams.File;
import slangc.streams.LogWriter;
import slangc.streams.VFS;
import slangc.streams.SimpleVFS;
import slangc.api.BytecodeTarget;
import slangc.api.CompilerWorld;
import slangc.api.Reporter;
import slangc.api.TypeOption;
import slangc.parser.Annotation;
import slangc.parser.Branch;
import slangc.parser.CleopatraModeLanguage;
import slangc.parser.LegacyLanguage;
import slangc.parser.Node;
import slangc.parser.Token;
public class CompilerMain {
public static int a(int i) {
Log.line("" + i);
return i;
}
public static void b(int a, int b) {
Log.line(a + " " + b);
}
public static void usage(String[] args, int argi, String message) {
Log.line("USAGE:\n\tTODO...\n" + message);
if (message != null) {
throw new Error("TODO: Safe exit"); //System.exit(1);
}
}
private static void doAddSource(CompilerWorld world, File file, boolean isReference) throws Error {
recursiveAddSource(world, null, file, isReference);
}
private static byte[] getFileBytes(File f) throws Error {
FileInput in = f.openInput();
byte[] out = new byte[(int) f.size()];
in.readBuffer(out, 0, out.length);
in.close();
return out;
}
private static void recursiveAddSource(CompilerWorld world, String packagename, File file, boolean isReference) throws Error {
File[] subs = file.list();
if (subs == null) {
//Log.line(" > Processing " + (isReference ? "referenced" : "included") + " file " + file.path());
if (world.matchesIgnorePattern(file.name())) {
//Log.line("Ignoring '" + file.path() + "'...");
} else if (world.matchesDataPattern(file.name())) {
//Log.line("Adding data file '" + file.path() + "'...");
if (!isReference) world.addDataFile(packagename, file.name(), getFileBytes(file), null, null);
} else if (world.matchesSourcePattern(file.name())) {
//Log.line("Adding source file '" + file.path() + "'...");
world.addSource(/*new SimpleSource(file)*/ new UnicodeSource(file), isReference);
} else {
throw new Error("Unrecognised file extension for '" + file.path() + "'");
//Log.line("Ignoring " + file.path() + "...");
}
} else {
if (packagename == null) {
packagename = ""; // This should be used for default/outer directory
} else if (packagename.equals("")) {
packagename = file.name();
} else {
packagename = packagename + "." + file.name();
}
//Log.line("Scanning directory '" + file.path() + "' (as package " + packagename + ")...");
for (int i = 0; i < subs.length; i++) {
recursiveAddSource(world, packagename, subs[i], isReference);
}
}
}
public static void main(String[] args) {
Log.line("Zak's Burrito Compiler, build #13-ish");
//Log.line("Hello, ٣١٤١٥=" + ٣١٤١٥);
int i = 0;
VFS vfs = new SimpleVFS();
CompilerWorld world = new CompilerWorld();
world.addSourcePattern("*.sauce");
/*
world.addIgnorePattern("*.foo");
world.addDataPattern("bar");
*/
/*for (i = 0; i < args.length; i++) {
Log.line("Arg #" + i + " is '" + args[i] + "'");
}
i = 0;*/
boolean doingSomething = false;
Reporter reporter = null;
//Log.line("Doing args...");
//Log.startTracing();
try {
while (i < args.length) {
//Log.line("Handling Arg #" + i + " is '" + args[i] + "'");
/* If it's a "-b" flag, then we translate it into corresponding "-a" and "-r" flags. */
if (args[i].startsWith("-b")) {
if (args[i].intsLength() > 2) {
String path = args[i].sub(2);
args = ArgsLoader.remove(args, i);
args = ArgsLoader.insert(args, i, new String[] {"-a", path + "/compiler.wrap", "-r", path});
} else {
if (i + 1 >= args.length) {
usage(args, i + 1, "Expecting filename following -a flag");
return;
}
String path = args[i+1];
args = ArgsLoader.remove(args, i);
args = ArgsLoader.remove(args, i);
args = ArgsLoader.insert(args, i, new String[] {"-a", path + "/compiler.wrap", "-r", path});
}
/*for (int x = 0; x < args.length; x++) {
Log.line("Arg #" + x + " = '" + args[x] + "'");
}
System.exit(-1);*/
}
/* If it's a "-a" flag, then we want to load the arguments from a file, insert them in the array,
* then continue processing!
*/
if (args[i].startsWith("-a")) {
if (args[i].intsLength() > 2) {
Log.line("NOTE: Loading compiler arguments from " + args[i].sub(2));
String[] newArgs = ArgsLoader.loadArgs(new UnicodeSource(vfs.file(args[i].sub(2))));
args = ArgsLoader.remove(args, i);
args = ArgsLoader.insert(args, i, newArgs);
} else {
if (i + 1 >= args.length) {
usage(args, i + 1, "Expecting filename following -a flag");
return;
}
Log.line("NOTE: Loading compiler arguments from " + args[i+1]);
String[] newArgs = ArgsLoader.loadArgs(new UnicodeSource(vfs.file(args[i+1])));
args = ArgsLoader.remove(args, i);
args = ArgsLoader.remove(args, i);
args = ArgsLoader.insert(args, i, newArgs);
}
/*for (int x = 0; x < args.length; x++) {
Log.line("Arg #" + x + " = '" + args[x] + "'");
}
System.exit(-1);*/
}
//Log.line("Handling Arg #" + i + " is '" + args[i] + "'");
if (args[i].equals("--provides-version")) {
if (i + 2 >= args.length) {
usage(args, i, "Expected name and version following --provides-version");
return;
}
world.addProvidesVersion(args[i + 1], args[i + 2]);
i += 2;
} else if (args[i].equals("--depends-version")) {
if (i + 2 >= args.length) {
usage(args, i, "Expected name and version following --depends-version");
return;
}
world.addDependsVersion(args[i + 1], args[i + 2]);
i += 2;
} else if (args[i].equals("--source-pattern")) {
if (i + 1 >= args.length) {
usage(args, i, "Expected source pattern following --source-pattern (e.g. \"*.slang\" - probably with the quotes)");
return;
}
world.addSourcePattern(args[i + 1]);
i += 1;
} else if (args[i].equals("--ignore-pattern")) {
if (i + 1 >= args.length) {
usage(args, i, "Expected ignore pattern following --ignore-pattern (e.g. \"*.project\" - probably with the quotes)");
return;
}
world.addIgnorePattern(args[i + 1]);
i += 1;
} else if (args[i].equals("--data-pattern")) {
if (i + 1 >= args.length) {
usage(args, i, "Expected source pattern following --data-pattern (e.g. \"*.png\" - probably with the quotes)");
return;
}
world.addDataPattern(args[i + 1]);
i += 1;
} else if (args[i].equals("--global-import")) {
if (i + 1 >= args.length) {
usage(args, i, "Expected package name following --global-import");
return;
}
world.addGlobalImport(args[i + 1]);
i += 1;
} else if (args[i].equals("--alias-type")) {
if (i + 2 >= args.length) {
usage(args, i, "Expected alias and target type names following --alias-type");
return;
}
world.addAliasType(args[i + 1], args[i + 2]);
i += 2;
} else if (args[i].equals("--alias-package")) {
if (i + 2 >= args.length) {
usage(args, i, "Expected alias and target package names following --alias-package");
return;
}
world.addAliasPackage(args[i + 1], args[i + 2]);
i += 2;
} else if (args[i].equals("--main")) {
if (i + 1 >= args.length) {
usage(args, i, "Expected type name following --main");
return;
}
world.addMainType(args[i + 1]);
i += 1;
} else if (args[i].equals("--special-type-format")) {
if (i + 3 >= args.length) {
usage(args, i, "Expected kind name, type name and runtime-specific format string following --special-type-format");
return;
}
TypeOption.Kind k;
k = (TypeOption.Kind) TypeOption.Kind.lookup(TypeOption.Kind.class, args[i + 1]);
if (k == null) {
usage(args, i+1, "Invalid kind name");
return;
}
world.addSpecialType(k, args[i + 2], args[i + 3]);
i += 3;
} else if (args[i].equals("--special-type")) {
if (i + 2 >= args.length) {
usage(args, i, "Expected kind name and type name following --special-type");
return;
}
TypeOption.Kind k;
try {
k = (TypeOption.Kind) TypeOption.Kind.lookup(TypeOption.Kind.class, args[i + 1]);
} catch(Error e) {
e.log();
Log.line("Name of VOID is '" + TypeOption.Kind.VOID.name() + "'");
usage(args, i+1, "Invalid kind name");
return;
}
world.addSpecialType(k, args[i + 2], null);
i += 2;
} else if (args[i].equals("--builtin-type")) {
if (i + 2 >= args.length) {
usage(args, i, "Expected kind name and type name following --builtin-type");
return;
}
TypeOption.Kind k;
try {
k = (TypeOption.Kind) TypeOption.Kind.lookup(TypeOption.Kind.class, args[i + 1]);
} catch(Error e) {
usage(args, i+1, "Invalid kind name");
return;
}
world.addBuiltinType(k, args[i + 2], null);
i += 2;
} else if (args[i].equals("--meta")) {
if (i + 2 >= args.length) {
usage(args, i, "Expected key and typeName following --meta");
return;
}
world.addMeta(false, args[i + 1], args[i + 2]);
i += 2;
} else if (args[i].equals("--important-meta")) {
if (i + 2 >= args.length) {
usage(args, i, "Expected key and typeName following --important-meta");
return;
}
world.addMeta(true, args[i + 1], args[i + 2]);
i += 2;
} else if (args[i].startsWith("-r")) {
if (args[i].ints().length > 2) {
doAddSource(world, vfs.file(args[i].sub(2)), true);
doingSomething = true;
} else {
i++;
if (i >= args.length) {
usage(args, i, "Expecting filename following -r flag");
return;
}
doAddSource(world, vfs.file(args[i]), true);
doingSomething = true;
}
} else if (args[i].startsWith("-o")) {
if (args[i].ints().length > 2) {
world.setTarget(new BytecodeTarget(new SimpleBytecodeOutput(vfs.file(args[i].sub(2)).openOutput())));
//doingSomething = true;
} else {
i++;
if (i >= args.length) {
usage(args, i, "Expecting filename following -o flag");
return;
}
world.setTarget(new BytecodeTarget(new SimpleBytecodeOutput(vfs.file(args[i]).openOutput())));
//doingSomething = true;
}
} else if (args[i].equals("--compliments-to-the-chef") || args[i].equals("--gluten-free")) {
Log.line("**************************************************");
String start = "* Salt Sprinkling Mode ";
boolean merciless = args[i].equals("--gluten-free");
CleopatraModeLanguage herMajesty = new CleopatraModeLanguage(!merciless);
herMajesty.addMedu(CleopatraModeLanguage.Medu.NUBIAN);
herMajesty.addMedu(CleopatraModeLanguage.Medu.COPTIC);
world.setLanguage(herMajesty);
Log.line(start + (merciless ? " TURBO *" : "ACTIVATED *"));
Log.line("**************************************************");
//herMajesty.printTable(System.err);
//return;
} else if (args[i].equals("-ll0")) {
world.setLanguage(new LegacyLanguage(0));
} else if (args[i].equals("-ll1")) {
world.setLanguage(new LegacyLanguage(1));
} else if (args[i].equals("-ll2")) {
world.setLanguage(new LegacyLanguage(2));
} else if (args[i].equals("-ll3")) {
world.setLanguage(new LegacyLanguage(3));
} else if (args[i].equals("-ll4")) {
world.setLanguage(new LegacyLanguage(4));
} else if (args[i].equals("-ll5")) {
world.setLanguage(new LegacyLanguage(5));
} else if (args[i].equals("-ll6")) {
world.setLanguage(new LegacyLanguage(6));
} else if (args[i].equals("-ll7")) {
world.setLanguage(new LegacyLanguage(7));
} else if (args[i].equals("-ll8")) {
world.setLanguage(new LegacyLanguage(8));
} else if (args[i].equals("-ll9")) {
world.setLanguage(new LegacyLanguage(9));
} else if (args[i].equals("-ll10")) {
world.setLanguage(new LegacyLanguage(10));
} else if (args[i].equals("-ll11")) {
world.setLanguage(new LegacyLanguage(11));
} else if (args[i].equals("-ll12")) {
world.setLanguage(new LegacyLanguage(12));
} else if (args[i].equals("-ll13")) {
world.setLanguage(new LegacyLanguage(13));
} else if (args[i].equals("-ll14")) {
world.setLanguage(new LegacyLanguage(14));
} else if (args[i].equals("-ll15")) {
world.setLanguage(new LegacyLanguage(15));
} else if (args[i].equals("-ll16")) {
world.setLanguage(new LegacyLanguage(16));
} else if (args[i].equals("--language-forget")) {
if (i + 1 >= args.length) {
usage(args, i, "Expecting setting name following --language-forget");
return;
}
if (!world.getLanguage().applySetting(args[i+1], null, true, false)) {
usage(args, i+1, "Invalid setting");
return;
}
i += 1;
} /*else if (args[i].equals("--language-set")) {
if (i + 2 >= args.length) {
usage(args, i, "Expecting setting name and value following --language-set");
return;
}
if (!world.getLanguage().applySetting(args[i+1], args[i+2], false, false)) {
usage(args, i+2, "Invalid setting");
return;
}
i += 2;
}*/ else if (args[i].equals("--language-add")) {
if (i + 2 >= args.length) {
usage(args, i, "Expecting setting name and value following --language-append");
return;
}
if (!world.getLanguage().applySetting(args[i+1], args[i+2], false, true)) {
usage(args, i+2, "Invalid setting");
return;
}
i += 2;
} else if (args[i].equals("--array-length-name")) {
if (i + 1 >= args.length) {
usage(args, i, "Expecting setting name following --array-length-name");
return;
}
world.addArrayLengthName(args[i+1]);
i += 1;
} else if (args[i].equals("--errors-brief")) {
world.setErrorVerbosity(0);
} else if (args[i].equals("--errors-nice")) {
world.setErrorVerbosity(2);
} else if (args[i].equals("--errors-ast")) {
world.setErrorVerbosity(5);
} else if (args[i].equals("--errors-full-ast")) {
world.setErrorVerbosity(10);
} else if (args[i].equals("--cache-dir")) {
//Log.line("WTF...");
if (i + 1 >= args.length) {
usage(args, i, "Expecting directory path following --cache-dir");
return;
}
//Log.line("Trying to set cache manager...");
world.setCacheManager(new SimpleCacheManager(vfs.file(args[i+1])));
//Log.line("Done.");
i += 1;
} else {
Log.line("Adding regular sources '" + args[i] + "'");
doAddSource(world, vfs.file(args[i]), false);
doingSomething = true;
}
i++;
}
if (!doingSomething) {
usage(args, i, "Expecting something to do! Try listing some source files?");
}
if (reporter == null) {
reporter = new SimpleReporter();
}
world.setReporter(reporter);
if (world.build()) {
Log.line("Compilation completed.");
} else {
Log.line("Compilation terminated without finishing.");
}
} catch (Error e) {
e.log();
// TODO: Is more reporting needed here?
}
//SimpleSource src = new SimpleSource("package x.y\nimport z.*; import foo.bar.Baz;\npublic final enum X extends a.B, C{X,Y,private static Z,;} class Foo extends Bar {\nvoid x(int a){{}}\nint a = 1, b;\npublic Foo(int... nums){}}\n/* comment 1 */\n// comment 2\nclass Documented {\n/* look, an array of arrays: */\nint[][] arrz = null;\nDocumented(){if(true){return 1;}else{return;}int x = add(1,z().foo[1].mul(2,3)), y = (z).foo();n();x++; x *= 2; x = 1 + 2 * -3 + new fencom.Object;\nx = \"foo bar\";\n}\n}\n");//int add(int x, int y){\nreturn x + y;\n}
/*Scan scan = new Scan(new Language(), src);
int n = scan.scanPedantic();
Log.line("Scanned " + n + " tokens:");
for (int i = 0; i < scan.countTokens(); i++) {
Log.line(" > " + scan.getToken(i));
}
Parse p = new Parse();
Node u = p.parseUnit(scan);
Log.line("Finished parsing!");
// Was just for testing order of operations: b(a(1), a(2));
dump(System.out, u);
*/
}
@SuppressWarnings("unused")
private static void dump(LogWriter out, Node n) {
dump(out, n, "", " ");
}
private static void dump(LogWriter out, Node n, String curindent, String subindent) {
if (n instanceof Branch) {
dumpBranch(out, (Branch) n, curindent, subindent);
} else if (n instanceof Token) {
dumpToken(out, (Token) n, curindent, subindent);
} else if (n instanceof Annotation) {
dumpAnnotation(out, (Annotation) n, curindent, subindent);
} else if (n == null) {
out.println(curindent + "-! UH-OH !- null");
} else {
out.println(curindent + "-! TO-DO !- code to dump " + n);
}
}
private static void dumpAnnotations(LogWriter out, Node n, String curindent, String subindent) {
for (int i = 0; i < n.countAnnotations(); i++) {
dump(out, n.getAnnotation(i), curindent + subindent, subindent);
}
}
private static void dumpBranch(LogWriter out, Branch b, String curindent, String subindent) {
out.println(curindent + "-> " + b.getNodeType());
dumpAnnotations(out, b, curindent, subindent);
for (int i = 0; i < b.countSubnodes(); i++) {
dump(out, b.getSubnode(i), curindent + subindent, subindent);
}
}
private static void dumpToken(LogWriter out, Token t, String curindent, String subindent) {
out.println(curindent + "-. " + t);
dumpAnnotations(out, t, curindent, subindent);
}
private static void dumpAnnotation(LogWriter out, Annotation a, String curindent, String subindent) {
out.println(curindent + "-+ " + a);
dumpAnnotations(out, a, curindent, subindent);
}
}

View File

@@ -0,0 +1,54 @@
package slangc.sdk;
import slang.streams.SyncOutput;
import slangc.streams.ArrayOutput;
import slangc.streams.FileOutput;
import slangc.api.BytecodeOutput;
public class SimpleBytecodeOutput extends BytecodeOutput {
private SyncOutput<byte> out;
public SimpleBytecodeOutput() {
this.out = new ArrayOutput();
}
public SimpleBytecodeOutput(FileOutput out) {
//try {
this.out = out; //new FileOutput(outname);
//} catch (Error e) {
// throw new Error("Couldn't open output stream", e);
//}
}
public SimpleBytecodeOutput(SyncOutput<byte> out) {
this.out = out;
}
@Override
public void processByte(byte b) {
//byte[] buf = new byte[1];
//int tmp = b + 0;
//buf[0] = (byte) tmp; // TODO: More thorough type-checking??
try {
if (out.writeBuffer(new byte[]{b}, 0, 1) != 1) {
throw new Error("Failed to write byte to output stream");
}
} catch (Error e) {
throw new Error("Couldn't write to output stream", e);
}
}
@Override
public void endOfFile() {
try {
out.close();
} catch (Error e) {
throw new Error("Couldn't close output stream", e);
}
out = null;
}
public SyncOutput<byte> getOut() {
return out;
}
}

View File

@@ -0,0 +1,34 @@
package slangc.sdk;
import slangc.api.CacheManager;
import slangc.streams.File;
import slang.streams.SyncInput;
import slang.streams.SyncOutput;
public class SimpleCacheManager extends CacheManager {
public File outerDir;
public SimpleCacheManager(File outerDir) {
this.outerDir = outerDir;
}
public boolean looksReady(String cacheName) {
return ((int)outerDir.getVFS().size(outerDir.path() + "/" + cacheName)) > 0;
}
public SyncInput<byte> getInput(String cacheName) {
if (looksReady(cacheName)) {
//Log.line("I'm gonna fuckin try it");
return outerDir.getVFS().openInput(outerDir.path() + "/" + cacheName);
} else {
return null;
}
}
public SyncOutput<byte> getOutput(String cacheName) {
if (looksReady(cacheName)) {
return null;
}
return outerDir.getVFS().openOutput(outerDir.path() + "/" + cacheName);
}
}

View File

@@ -0,0 +1,16 @@
package slangc.sdk;
import slangc.api.NullReporter;
public class SimpleReporter extends NullReporter {
public SimpleReporter() {
// TODO Auto-generated constructor stub
}
@Override
public void note(String topic, String text) {
Log.line(topic + ": " + text);
}
}

View File

@@ -0,0 +1,54 @@
package slangc.sdk;
import slangc.streams.FileInput;
import slangc.streams.File;
import slangc.parser.Source;
public class SimpleSource extends Source {
byte[] source;
public SimpleSource(File file) throws Error {
this(file.path(), file);
}
public SimpleSource(String filename, File file) throws Error {
super(filename);
FileInput is = file.openInput();
byte[] fileData = new byte[(int) file.size()];
/*int i =*/ is.read(fileData);
//System.out.println("Read " + i + " bytes from " + file);
is.close();
this.source = String.construct(fileData);
//sourceFile = this.source.replace("\r\n", "\n");
//System.out.println("GOT:\n" + sourceFile);
}
public SimpleSource(String filename, String source) {
super(filename);
this.source = source;
}
public SimpleSource(String source) {
this.source = source;
}
@Override
public int getIndexLength() {
return source.length;
}
@Override
public int getCharacter(int index) {
if (isIndexWithinBounds(index)) {
return (int) source[index]; //.charAt(index);
} else {
return 0;
}
}
@Override
public int getNextIndex(int currentIndex) {
// TODO Auto-generated method stub
return currentIndex + 1;
}
}

View File

@@ -0,0 +1,5 @@
package slangc.sdk;
public class UnicodeCharacter {
}

View File

@@ -0,0 +1,97 @@
package slangc.sdk;
import slangc.streams.FileInput;
import slangc.streams.File;
import slangc.parser.Source;
public class UnicodeSource extends Source {
int[] source;
public UnicodeSource(File file) throws Error {
this(file.path(), file);
}
public UnicodeSource(String filename, File file) throws Error {
super(filename);
FileInput is = file.openInput();
byte[] fileData = new byte[(int) file.size()];
int ln = is.read(fileData);
//System.out.println("Read " + i + " bytes from " + file);
is.close();
// This is a lot easier in Slang since the String class handles both 8-bit and 32-bit conversions naturally:
//Log.line("About to construct...");
String strsource = String.construct(fileData); // This will assume a standard 8-bit encoding (compressed characters)
//Log.line("Done constructing!");
source = strsource.ints(); // This will assume a standard 32-bit encoding (one value per character)
//String strsource = new String(fileData, "UTF-8");
//int ncp = strsource.codePointCount(0, strsource.length());
//source = new int[ncp];
//int cpi = 0;
//int i = 0;
//while (i < strsource.length()) {
// if (cpi >= ncp) {
// throw new Error("Unicode error: Number of characters (at least " + cpi + ") is greater than number of expected characters ("+ncp+")");
// }
// int cp = strsource.codePointAt(i);
// int cpl = Character.toChars(cp).length;
// source[cpi] = cp;
// i += cpl;
// cpi++;
//}
//source = this.source.replace("\r\n", "\n");
//System.out.println("GOT:\n" + source);
}
public UnicodeSource(String filename, int[] source) {
super(filename);
this.source = source;
}
public UnicodeSource(int[] source) {
this.source = source;
}
@Override
public int getIndexLength() {
return source.length;
}
@Override
public int getCharacter(int index) {
if (isIndexWithinBounds(index)) {
return source[index];
} else {
return 0;
}
}
/*
int lastidx = 0;
int lastlen = 0;
String laststr = null;
public String getString(int index, int len) {
if (index == lastidx && len == lastlen) {
return laststr;
} else {
lastidx = index;
lastlen = len;
laststr = super.getString(index, len);
return laststr;
}
}*/
public String getString(int index, int len) {
if (index + len > source.length) {
return super.getString(index, len);
}
int[] vals = new int[len];
for (int i = 0; i < len; i++) {
vals[i] = source[index+i];
}
return String.construct(vals);
}
@Override
public int getNextIndex(int currentIndex) {
return currentIndex + 1;
}
}