Initial commit of main compiler sources (or should I say ... SAUCES!)
This commit is contained in:
1646
slangc/api/BytecodeHeap.sauce
Normal file
1646
slangc/api/BytecodeHeap.sauce
Normal file
File diff suppressed because it is too large
Load Diff
1023
slangc/api/BytecodeInstructionWriter.sauce
Normal file
1023
slangc/api/BytecodeInstructionWriter.sauce
Normal file
File diff suppressed because it is too large
Load Diff
29
slangc/api/BytecodeOutput.sauce
Normal file
29
slangc/api/BytecodeOutput.sauce
Normal file
@ -0,0 +1,29 @@
|
||||
package slangc.api;
|
||||
|
||||
public abstract class BytecodeOutput {
|
||||
protected int count = 0;
|
||||
public abstract void endOfFile();
|
||||
public abstract void processByte(byte b);
|
||||
|
||||
public final void write8(byte b) {
|
||||
processByte(b);
|
||||
count++;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void write16(short w) {
|
||||
write8((byte)w);
|
||||
write8((byte)(w >> 8));
|
||||
}
|
||||
public void write32(int w) {
|
||||
write16((short)w);
|
||||
write16((short)(w >> 16));
|
||||
}
|
||||
public void write64(long w) {
|
||||
write32((int)w);
|
||||
write32((int)(w >> 32));
|
||||
}
|
||||
}
|
339
slangc/api/BytecodeTarget.sauce
Normal file
339
slangc/api/BytecodeTarget.sauce
Normal file
@ -0,0 +1,339 @@
|
||||
package slangc.api;
|
||||
|
||||
import slang.data.List;
|
||||
import slang.data.Map;
|
||||
import slangc.api.BytecodeHeap;
|
||||
import slangc.bytecode.MethodSignature;
|
||||
import slangc.bytecode.TypeSignature;
|
||||
import slangc.model.FieldModel;
|
||||
import slangc.model.Flags;
|
||||
import slangc.model.MethodModel;
|
||||
import slangc.model.ParameterModel;
|
||||
import slangc.model.UserTypeModel;
|
||||
import slangc.model.statements.BlockStatement;
|
||||
import slangc.model.BuiltinTypeModel;
|
||||
|
||||
public class BytecodeTarget extends CompilerTarget {
|
||||
final BytecodeHeap heap;
|
||||
final BytecodeOutput output;
|
||||
private final List<ReprocessType> types = new List<ReprocessType>();
|
||||
|
||||
private final Map<TypeSignature,BytecodeInstructionWriter.StackType> cachedStackTypes = new Map<TypeSignature,BytecodeInstructionWriter.StackType>();
|
||||
|
||||
|
||||
|
||||
public BytecodeInstructionWriter.StackType stackType(TypeSignature type) {
|
||||
if (!cachedStackTypes.hasKey(type)) {
|
||||
BytecodeInstructionWriter.StackType t = calculateStackType(type);
|
||||
cachedStackTypes.set(type, t);
|
||||
return t;
|
||||
}
|
||||
return cachedStackTypes.get(type);
|
||||
}
|
||||
|
||||
public BytecodeInstructionWriter.StackType calculateStackType(TypeSignature type) {
|
||||
if (type.mappableEquals(TypeSignature.VOID)) {
|
||||
return BytecodeInstructionWriter.StackType.VOID;
|
||||
} /*else if (type.mappableEquals(getSystem().getDefaultBooleanType().getTypeSignature())) {
|
||||
return BytecodeInstructionWriter.StackType.BIT;
|
||||
} else if (type.mappableEquals(getSystem().getDefaultFloat32Type().getTypeSignature())) {
|
||||
return BytecodeInstructionWriter.StackType.FLOAT32;
|
||||
} else if (type.mappableEquals(getSystem().getDefaultFloat64Type().getTypeSignature())) {
|
||||
return BytecodeInstructionWriter.StackType.FLOAT64;
|
||||
} else if (type.mappableEquals(getSystem().getDefaultInt64Type().getTypeSignature())) {
|
||||
return BytecodeInstructionWriter.StackType.INT64;
|
||||
} else if (getSystem().matchesTypeOption(TypeOption.Kind.DUCK, type)) {
|
||||
return BytecodeInstructionWriter.StackType.DUCK;
|
||||
}*/ else if (getSystem().getType(type) instanceof BuiltinTypeModel) {
|
||||
for (int i = 0; i < BytecodeInstructionWriter.StackType.lookupCount(BytecodeInstructionWriter.StackType.class); i++) {
|
||||
if (getSystem().matchesTypeOption((TypeOption.Kind)TypeOption.Kind.lookup(TypeOption.Kind.class, i), type)) {
|
||||
return (BytecodeInstructionWriter.StackType)BytecodeInstructionWriter.StackType.lookup(BytecodeInstructionWriter.StackType.class, i);
|
||||
}
|
||||
}
|
||||
return BytecodeInstructionWriter.StackType.INT32;
|
||||
} else {
|
||||
for (int i = 0; i < BytecodeInstructionWriter.StackType.lookupCount(BytecodeInstructionWriter.StackType.class); i++) {
|
||||
if (getSystem().matchesTypeOption((TypeOption.Kind)TypeOption.Kind.lookup(TypeOption.Kind.class, i), type)) {
|
||||
return (BytecodeInstructionWriter.StackType)BytecodeInstructionWriter.StackType.lookup(BytecodeInstructionWriter.StackType.class, i);
|
||||
}
|
||||
}
|
||||
return BytecodeInstructionWriter.StackType.OBJECT;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ReprocessType {
|
||||
UserTypeModel type;
|
||||
boolean addToMainList;
|
||||
|
||||
ReprocessType(UserTypeModel type, boolean addToMainList) {
|
||||
this.type = type;
|
||||
this.addToMainList = addToMainList;
|
||||
}
|
||||
}
|
||||
|
||||
public BytecodeTarget(BytecodeOutput output, BytecodeHeap heap) {
|
||||
this.output = output;
|
||||
this.heap = heap;
|
||||
}
|
||||
|
||||
public BytecodeTarget(BytecodeOutput output) {
|
||||
this(output, new BytecodeHeap(1000000000, true));
|
||||
}
|
||||
|
||||
public void generateFieldInitialisers(UserTypeModel t, BytecodeInstructionWriter w, boolean isStaticInit) {
|
||||
for (int i = 0; i < t.countFieldMembers(); i++) {
|
||||
FieldModel f = t.getFieldMember(i);
|
||||
if (isStaticInit && f.isEnumField()) {
|
||||
w.genNewObject(t.getDefaultInstanceConstructor().getMethodSignature());
|
||||
w.genStore(f.getFieldSignature());
|
||||
} else if (f.hasInitialiser() && f.isStatic() == isStaticInit) {
|
||||
TypeSignature storing = f.getInitialisationExpression().generate(w);
|
||||
if (!storing.mappableEquals(f.getStorageType().getTypeSignature())) {
|
||||
w.genConvert(storing, f.getStorageType().getTypeSignature());
|
||||
storing = f.getStorageType().getTypeSignature();
|
||||
}
|
||||
if (!f.isStatic()) {
|
||||
w.genThis();
|
||||
}
|
||||
w.genStore(f.getFieldSignature());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void visitField(BytecodeHeap.ObjectLike typ, FieldModel m) {
|
||||
BytecodeHeap.ObjectLike member = heap.newField(typ, m.getFlags(), m.getFieldSignature());
|
||||
for (int i = 0; i < m.getAttributes().countTranslations(); i++) {
|
||||
heap.addMemberTranslation(member, m.getAttributes().getTranslation(i).language, m.getAttributes().getTranslation(i).name);
|
||||
}
|
||||
}
|
||||
|
||||
private void visitMethod(BytecodeHeap.ObjectLike typ, MethodModel m) {
|
||||
BytecodeHeap.ObjectLike member = heap.newMethod(typ, m.getFlags(), m.getMethodSignature(), m.countLocals());
|
||||
for (int i = 0; i < m.getAttributes().countTranslations(); i++) {
|
||||
heap.addMemberTranslation(member, m.getAttributes().getTranslation(i).language, m.getAttributes().getTranslation(i).name);
|
||||
}
|
||||
if (m.hasBody() || m.isConstructor()) {
|
||||
BytecodeInstructionWriter w = new BytecodeInstructionWriter(this, m.getOwner(), member);
|
||||
w.pushSource(m.getSource());
|
||||
boolean initAfterFirstStatement = false;
|
||||
if (m.isStaticInitialisation()) {
|
||||
generateFieldInitialisers((UserTypeModel)m.getOwner(), w, true);
|
||||
} else if (m.isConstructor()) {
|
||||
if (m.checkExplicitBaseConstructorCall(true)) {
|
||||
// This will have "approved" the constructor call location,
|
||||
// But we need to check if it was actually a super(...) call
|
||||
// (and not a call to another this(...) constructor)
|
||||
// before we go around re-initialising any already-initialised fields!
|
||||
if (m.checkExplicitBaseConstructorCall(false)) {
|
||||
initAfterFirstStatement = true;
|
||||
}
|
||||
} else {
|
||||
if (m.hasBody()) {
|
||||
w.genDefaultSuperConstructorCall();
|
||||
} else {
|
||||
// This handles synthetic constructors
|
||||
// These naturally pass all arguments to the super-constructor
|
||||
for (int i = 0; i < m.countParameters(); i++) {
|
||||
ParameterModel p = m.getParameter(i);
|
||||
w.genLoadLocalOrParam(p.getStorageType().getTypeSignature(), p.getIndex());
|
||||
}
|
||||
w.genNestedConstructorCall(m.getPrototype().getMethodSignature());
|
||||
}
|
||||
generateFieldInitialisers((UserTypeModel)m.getOwner(), w, false);
|
||||
}
|
||||
}
|
||||
if (m.countExceptions() > 0) {
|
||||
BytecodeHeap.ObjectLike o = getHeap().newObjectLike(BytecodeHeap.StandardClass.SIMPLEARRAY, m.countExceptions());
|
||||
for (int i = 0; i < m.countExceptions(); i++) {
|
||||
o.setElement(i, getHeap().getTypeSignature(m.getException(i).getTypeSignature()));
|
||||
}
|
||||
member.setElement(BytecodeHeap.MethodFields.THROWS.value, o);
|
||||
}
|
||||
if (m.hasBody()) {
|
||||
/* Manually loop through statements to ensure fields are initialised if needed. */
|
||||
if (m.getBody() instanceof BlockStatement) {
|
||||
BlockStatement block = (BlockStatement) m.getBody();
|
||||
w.pushSource(block.getSource());
|
||||
if (block.countInnerStatements() == 0 && initAfterFirstStatement) {
|
||||
generateFieldInitialisers((UserTypeModel)m.getOwner(), w, false);
|
||||
}
|
||||
for (int i = 0; i < block.countInnerStatements(); i++) {
|
||||
block.getInnerStatement(i).generate(w);
|
||||
if (i == 0 && initAfterFirstStatement) {
|
||||
generateFieldInitialisers((UserTypeModel)m.getOwner(), w, false);
|
||||
}
|
||||
}
|
||||
w.popSource();
|
||||
} else {
|
||||
m.getBody().generate(w);
|
||||
if (initAfterFirstStatement) {
|
||||
generateFieldInitialisers((UserTypeModel)m.getOwner(), w, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
w.genEnd();
|
||||
w.popSource(m.getSource());
|
||||
}
|
||||
}
|
||||
|
||||
void generateImplicitStaticInit(UserTypeModel m, BytecodeHeap.ObjectLike typ) {
|
||||
int flags = Flags.MASK_METHOD | Flags.MASK_CONSTRUCTOR | Flags.MASK_STATIC | Flags.MASK_SYNTHETIC;
|
||||
BytecodeHeap.ObjectLike member = heap.newMethod(typ, flags, new MethodSignature(m.getTypeSignature(), MethodSignature.Kind.STATIC_INIT, TypeSignature.VOID, "static-init", new TypeSignature[0]), 0);
|
||||
BytecodeInstructionWriter w = new BytecodeInstructionWriter(this, m, member);
|
||||
w.pushSource(m.getParsed());
|
||||
generateFieldInitialisers(m, w, true);
|
||||
w.genEnd();
|
||||
w.popSource(m.getParsed());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitProvidesOrDepends(ProvidesOrDepends x) {
|
||||
if (x.provides) {
|
||||
heap.newProvides(x.name, x.version);
|
||||
} else {
|
||||
heap.newDepends(x.name, x.version, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMeta(boolean important, String key, String value) {
|
||||
heap.newMetadata(important, key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeOption(TypeOption o) {
|
||||
heap.registerRuntimeType(o.kind.value, o.kind.value, o.getTypeSignature(), o.formatopt, o.isBuiltin, o.isNumber, o.isFloat, o.isSigned, o.nbits);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDataFile(DataFile dataFile) {
|
||||
heap.newFile(dataFile.packagename, dataFile.innername, dataFile.data, dataFile.typeinfo, dataFile.debugname);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitType(UserTypeModel m, boolean addToMainList) {
|
||||
types.append(new ReprocessType(m, addToMainList));
|
||||
dryRun(m, addToMainList);
|
||||
}
|
||||
|
||||
private boolean firstDryRun = true;
|
||||
private void dryRun(UserTypeModel m, boolean addToMainList) {
|
||||
if (firstDryRun) {
|
||||
for (int i = 0; i <= 1024; i++) {
|
||||
//heap.getConstInt32(""+i);
|
||||
}
|
||||
firstDryRun = false;
|
||||
}
|
||||
heap.getTypeSignature(m.getTypeSignature());
|
||||
|
||||
for (int i = 0; i < m.countFieldMembers(); i++) {
|
||||
FieldModel f = m.getFieldMember(i);
|
||||
heap.getFieldSignature(f.getFieldSignature());
|
||||
}
|
||||
|
||||
for (int i = 0; i < m.countMethodMembers(); i++) {
|
||||
MethodModel mt = m.getMethodMember(i);
|
||||
if (!mt.isStaticInitialisation()) {
|
||||
//Log.line("For " + mt.toString() + "[" + mt.getMethodSignature().toString() + "] got " + heap.getMethodSignature(mt.getMethodSignature()).debugString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processType(UserTypeModel m, boolean addToMainList) {
|
||||
BytecodeHeap.ObjectLike typ = heap.newType(m.getFlags(), m.getTypeSignature());
|
||||
if (m.getBaseClass() != null) {
|
||||
typ.setElement(2, heap.getTypeSignature(m.getBaseClass().getTypeSignature()));
|
||||
}
|
||||
if (m.countInterfaces() > 0) {
|
||||
BytecodeHeap.ObjectLike ifcs = heap.newObjectLike(BytecodeHeap.StandardClass.SIMPLEARRAY, m.countInterfaces());
|
||||
typ.setElement(3, ifcs);
|
||||
for (int i = 0; i < m.countInterfaces(); i++) {
|
||||
ifcs.setElement(i, heap.getTypeSignature(m.getInterface(i).getTypeSignature()));
|
||||
}
|
||||
}
|
||||
|
||||
if (m.getSource() != null) {
|
||||
typ.setElement(BytecodeHeap.TypeFields.FILENAME.value, heap.getConstString(m.getSource().getFilename()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < m.countFieldMembers(); i++) {
|
||||
FieldModel f = m.getFieldMember(i);
|
||||
visitField(typ, f);
|
||||
}
|
||||
|
||||
boolean explicitStaticInit = false;
|
||||
|
||||
for (int i = 0; i < m.countMethodMembers(); i++) {
|
||||
MethodModel mt = m.getMethodMember(i);
|
||||
if (mt.isStaticInitialisation()) {
|
||||
explicitStaticInit = true;
|
||||
}
|
||||
visitMethod(typ, mt);
|
||||
}
|
||||
|
||||
if (!explicitStaticInit) {
|
||||
generateImplicitStaticInit(m, typ);
|
||||
}
|
||||
|
||||
if (addToMainList) {
|
||||
getHeap().getEntrypointsArray().appendElement(typ);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
for (int i = 0; i < types.count(); i++) {
|
||||
Log.line("Reprocessing type #" + i);
|
||||
ReprocessType t = types.get(i);
|
||||
Log.line("Reprocessing type " + t.type.toString());
|
||||
processType(t.type, t.addToMainList);
|
||||
}
|
||||
Log.line("FINISHING: " + quickReport());
|
||||
Log.line("in BytecodeTaget...");
|
||||
if (output != null) {
|
||||
heap.writeAll(output, "#!/usr/bin/env testvm", 3, 256, 1, 1);
|
||||
output.endOfFile();
|
||||
} else {
|
||||
Log.line("NO OUTPUT??");
|
||||
}
|
||||
}
|
||||
|
||||
public String strbytes(int size) {
|
||||
int orig = size;
|
||||
String result = "";
|
||||
|
||||
if (size > 1024*1024) {
|
||||
result += (size/(1024*1024)) + " MB";
|
||||
size %= (1024*1024);
|
||||
}
|
||||
|
||||
if (size > 1024) {
|
||||
if (!result.equals("")) {
|
||||
result += " ";
|
||||
}
|
||||
result += (size/1024) + " KB";
|
||||
size %= 1024;
|
||||
}
|
||||
|
||||
if (size != 0 || result.equals("")) {
|
||||
if (!result.equals("")) {
|
||||
result += " ";
|
||||
}
|
||||
result += size + " bytes";
|
||||
size = 0;
|
||||
}
|
||||
|
||||
result += " (" + /*String.format("%.4f",*/ (orig / (1024.0*1024.0)) + "MB)";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String quickReport() {
|
||||
return "Object table " + strbytes(heap.objectTableSize(3)) + " (" + (heap.highestUsedRecordIndex() + 1) + " entries), index size " + strbytes(heap.objectTableIndexSize(3, 256)) + ", data section " + strbytes(heap.dataSize(1)) + ": total file size " + strbytes(heap.fileSize(3, 256, 1, 1)) /*heap.objectTableSize(3) + heap.objectTableIndexSize(3, 256) + heap.dataSize(1))*/;
|
||||
}
|
||||
|
||||
public BytecodeHeap getHeap() {
|
||||
return heap;
|
||||
}
|
||||
}
|
13
slangc/api/CacheManager.sauce
Normal file
13
slangc/api/CacheManager.sauce
Normal file
@ -0,0 +1,13 @@
|
||||
package slangc.api;
|
||||
|
||||
import slang.streams.SyncInput;
|
||||
import slang.streams.SyncOutput;
|
||||
|
||||
public class CacheManager {
|
||||
public SyncInput<byte> getInput(String cacheName) {
|
||||
return null;
|
||||
}
|
||||
public SyncOutput<byte> getOutput(String cacheName) {
|
||||
return null;
|
||||
}
|
||||
}
|
34
slangc/api/CompilerPackage.sauce
Normal file
34
slangc/api/CompilerPackage.sauce
Normal file
@ -0,0 +1,34 @@
|
||||
package slangc.api;
|
||||
|
||||
import slangc.codegraph.DynamicPackage;
|
||||
|
||||
public class CompilerPackage extends DynamicPackage {
|
||||
private Unit[] units = new Unit[0];
|
||||
|
||||
public CompilerPackage() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompilerSet getEnclosingContainer() {
|
||||
// TODO Auto-generated method stub
|
||||
return (CompilerSet) super.getEnclosingContainer();
|
||||
}
|
||||
|
||||
public int countUnits() {
|
||||
return units.length;
|
||||
}
|
||||
|
||||
public void addUnit(Unit u) {
|
||||
if (u.getPackageName().equals(getSimpleName())) {
|
||||
Unit[] nunits = new Unit[units.length + 1];
|
||||
for (int i = 0; i < units.length; i++) {
|
||||
nunits[i] = units[i];
|
||||
}
|
||||
nunits[nunits.length - 1] = u;
|
||||
units = nunits;
|
||||
} else {
|
||||
throw new Error("Package name mismatch");
|
||||
}
|
||||
}
|
||||
}
|
43
slangc/api/CompilerSet.sauce
Normal file
43
slangc/api/CompilerSet.sauce
Normal file
@ -0,0 +1,43 @@
|
||||
package slangc.api;
|
||||
|
||||
import slangc.codegraph.DynamicSet;
|
||||
|
||||
public class CompilerSet extends DynamicSet {
|
||||
|
||||
public CompilerSet() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompilerWorld getEnclosingContainer() {
|
||||
return (CompilerWorld) super.getEnclosingContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompilerPackage getNamedElement(int index) {
|
||||
// TODO Auto-generated method stub
|
||||
return (CompilerPackage) super.getNamedElement(index);
|
||||
}
|
||||
|
||||
public CompilerPackage findPackageOrNull(String name) {
|
||||
for (int i = 0; i < countNamedElements(); i++) {
|
||||
CompilerPackage p = getNamedElement(i);
|
||||
if (p.getSimpleName().equals(name)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public CompilerPackage findPackageOrCreate(String name) {
|
||||
CompilerPackage result = findPackageOrNull(name);
|
||||
|
||||
if (result == null) {
|
||||
result = new CompilerPackage();
|
||||
result.setSimpleName(name);
|
||||
appendNamedElement(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
34
slangc/api/CompilerTarget.sauce
Normal file
34
slangc/api/CompilerTarget.sauce
Normal file
@ -0,0 +1,34 @@
|
||||
package slangc.api;
|
||||
|
||||
import slangc.model.SystemModel;
|
||||
import slangc.model.UserTypeModel;
|
||||
|
||||
public abstract class CompilerTarget {
|
||||
private SystemModel system;
|
||||
|
||||
public CompilerTarget() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public abstract void visitType(UserTypeModel m, boolean addToMainList);
|
||||
|
||||
public abstract void finish();
|
||||
|
||||
public abstract String quickReport();
|
||||
|
||||
public SystemModel getSystem() {
|
||||
return system;
|
||||
}
|
||||
|
||||
public void setSystem(SystemModel system) {
|
||||
this.system = system;
|
||||
}
|
||||
|
||||
public abstract void visitDataFile(DataFile dataFile);
|
||||
|
||||
public abstract void visitProvidesOrDepends(ProvidesOrDepends x);
|
||||
|
||||
public abstract void visitMeta(boolean important, String key, String value);
|
||||
|
||||
public abstract void visitTypeOption(TypeOption o);
|
||||
}
|
766
slangc/api/CompilerWorld.sauce
Normal file
766
slangc/api/CompilerWorld.sauce
Normal file
@ -0,0 +1,766 @@
|
||||
package slangc.api;
|
||||
|
||||
import slangc.codegraph.DynamicSet;
|
||||
import slangc.codegraph.DynamicWorld;
|
||||
import slangc.model.BuiltinTypeBehaviour;
|
||||
import slangc.model.PackageModel;
|
||||
import slangc.model.SystemModel;
|
||||
import slangc.model.TypeModel;
|
||||
import slangc.model.MethodModel;
|
||||
import slangc.model.UserTypeModel;
|
||||
import slangc.parser.Language;
|
||||
import slangc.parser.Source;
|
||||
|
||||
public class CompilerWorld extends DynamicWorld {
|
||||
private Reporter reporter = null;
|
||||
private Unit[] includedSources = new Unit[0];
|
||||
private Unit[] referencedSources = new Unit[0];
|
||||
private DynamicSet referencedSet;
|
||||
private DynamicSet includedSet;
|
||||
private Language language = new Language();
|
||||
private CompilerTarget target = null;
|
||||
private String[] sourceExtensions = new String[0];
|
||||
private String[] dataExtensions = new String[0];
|
||||
private String[] ignoreExtensions = new String[0];
|
||||
private DataFile[] dataFiles = new DataFile[0];
|
||||
private ProvidesOrDepends[] providesDepends = new ProvidesOrDepends[0];
|
||||
private String[] globalImports = new String[0];
|
||||
private MetaOrAlias[] aliasTypes = new MetaOrAlias[0];
|
||||
private MetaOrAlias[] aliasPackages = new MetaOrAlias[0];
|
||||
private MetaOrAlias[] importantMeta = new MetaOrAlias[0];
|
||||
private MetaOrAlias[] otherMeta = new MetaOrAlias[0];
|
||||
private TypeOption[] typeOptions = new TypeOption[0];
|
||||
private String[] mainTypes = new String[0];
|
||||
private CacheManager cacheManager = new CacheManager();
|
||||
|
||||
public CompilerWorld() {
|
||||
referencedSet = new DynamicSet();
|
||||
referencedSet.setSimpleName("<referenced>");
|
||||
appendNamedElement(referencedSet);
|
||||
includedSet = new DynamicSet();
|
||||
includedSet.setSimpleName("<included>");
|
||||
appendNamedElement(includedSet);
|
||||
}
|
||||
|
||||
public CacheManager getCacheManager() {
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
public void setCacheManager(CacheManager m) {
|
||||
cacheManager = m;
|
||||
}
|
||||
|
||||
private int errorVerbosity = 5;
|
||||
|
||||
public void setErrorVerbosity(int i) {
|
||||
errorVerbosity = i;
|
||||
}
|
||||
|
||||
public String[] arrayLengthNames = null;
|
||||
|
||||
public void addArrayLengthName(String n) {
|
||||
// NOTE: Adding any names will clear the default "length" definition!
|
||||
if (arrayLengthNames == null) {
|
||||
arrayLengthNames = new String[]{n};
|
||||
} else {
|
||||
String[] narr = new String[arrayLengthNames.length + 1];
|
||||
for (int i = 0; i < arrayLengthNames.length; i++) {
|
||||
narr[i] = arrayLengthNames[i];
|
||||
}
|
||||
narr[narr.length-1] = n;
|
||||
arrayLengthNames = narr;
|
||||
}
|
||||
}
|
||||
|
||||
public void setTarget(CompilerTarget t) {
|
||||
this.target = t;
|
||||
}
|
||||
|
||||
public CompilerTarget getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
private String[] addPatternArray(String[] arr, String ext) {
|
||||
for (int i = 0; i < arr.length; i++) {
|
||||
if (arr[i].equals(ext)) {
|
||||
return arr; // No need to add.
|
||||
}
|
||||
}
|
||||
String[] r = new String[arr.length + 1];
|
||||
for (int i = 0; i < r.length; i++) {
|
||||
if (i < arr.length) {
|
||||
r[i] = arr[i];
|
||||
} else {
|
||||
r[i] = ext;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
public void addSourcePattern(String ext) {
|
||||
sourceExtensions = addPatternArray(sourceExtensions, ext);
|
||||
}
|
||||
|
||||
public void addDataPattern(String ext) {
|
||||
dataExtensions = addPatternArray(dataExtensions, ext);
|
||||
}
|
||||
|
||||
public void addIgnorePattern(String ext) {
|
||||
ignoreExtensions = addPatternArray(ignoreExtensions, ext);
|
||||
}
|
||||
|
||||
private boolean matchesPatternArray(String[] exts, String name) {
|
||||
for (int i = 0; i < exts.length; i++) {
|
||||
if (exts[i].startsWith("*")) {
|
||||
//System.err.println("Testing '" + name + "' against extension '" + exts[i].sub(1) + "'");
|
||||
if (name.endsWith(exts[i].sub(1))) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
//System.err.println("Testing '" + name + "' against '" + exts[i] + "'");
|
||||
if (name.equals(exts[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean matchesSourcePattern(String filename) {
|
||||
return matchesPatternArray(sourceExtensions, filename);
|
||||
}
|
||||
|
||||
public boolean matchesDataPattern(String filename) {
|
||||
return matchesPatternArray(dataExtensions, filename);
|
||||
}
|
||||
|
||||
public boolean matchesIgnorePattern(String filename) {
|
||||
return matchesPatternArray(ignoreExtensions, filename);
|
||||
}
|
||||
|
||||
public void addGlobalImport(String x) {
|
||||
String[] newarr = new String[globalImports.length + 1];
|
||||
for (int i = 0; i < newarr.length; i++) {
|
||||
if (i < globalImports.length) {
|
||||
newarr[i] = globalImports[i];
|
||||
} else {
|
||||
newarr[i] = x;
|
||||
}
|
||||
}
|
||||
globalImports = newarr;
|
||||
}
|
||||
|
||||
private void addProvidesOrdepends(ProvidesOrDepends x) {
|
||||
ProvidesOrDepends[] newarr = new ProvidesOrDepends[providesDepends.length + 1];
|
||||
for (int i = 0; i < newarr.length; i++) {
|
||||
if (i < providesDepends.length) {
|
||||
newarr[i] = providesDepends[i];
|
||||
} else {
|
||||
newarr[i] = x;
|
||||
}
|
||||
}
|
||||
providesDepends = newarr;
|
||||
}
|
||||
|
||||
public void addProvidesVersion(String name, String version) {
|
||||
addProvidesOrdepends(new ProvidesOrDepends(true, name, version));
|
||||
}
|
||||
|
||||
public void addDependsVersion(String name, String version) {
|
||||
addProvidesOrdepends(new ProvidesOrDepends(false, name, version));
|
||||
}
|
||||
|
||||
private void addTypeOption(TypeOption o) {
|
||||
TypeOption[] r = new TypeOption[typeOptions.length + 1];
|
||||
for (int i = 0; i < r.length; i++) {
|
||||
if (i < typeOptions.length) {
|
||||
r[i] = typeOptions[i];
|
||||
} else {
|
||||
r[i] = o;
|
||||
}
|
||||
}
|
||||
typeOptions = r;
|
||||
}
|
||||
|
||||
public void addSpecialType(TypeOption.Kind kind, String typename, String formatOptions) {
|
||||
addTypeOption(new TypeOption(kind, typename, formatOptions));
|
||||
}
|
||||
|
||||
public void addBuiltinType(TypeOption.Kind kind, String typename, String formatOptions, boolean isDuck, boolean isNumber, boolean isFloat, boolean isSigned, int nbits) {
|
||||
addTypeOption(new TypeOption(kind, typename, formatOptions, true, isDuck, isNumber, isFloat, isSigned, nbits));
|
||||
}
|
||||
|
||||
public void addBuiltinType(TypeOption.Kind kind, String typename, String formatOptions) {
|
||||
switch (kind) {
|
||||
case TypeOption.Kind.BIT:
|
||||
addBuiltinType(kind, typename, formatOptions, false, false, false, false, 1);
|
||||
break;
|
||||
case TypeOption.Kind.INT8:
|
||||
addBuiltinType(kind, typename, formatOptions, false, true, false, true, 8);
|
||||
break;
|
||||
case TypeOption.Kind.INT16:
|
||||
addBuiltinType(kind, typename, formatOptions, false, true, false, true, 16);
|
||||
break;
|
||||
case TypeOption.Kind.INT32:
|
||||
addBuiltinType(kind, typename, formatOptions, false, true, false, true, 32);
|
||||
break;
|
||||
case TypeOption.Kind.INT64:
|
||||
addBuiltinType(kind, typename, formatOptions, false, true, false, true, 64);
|
||||
break;
|
||||
case TypeOption.Kind.UINT8:
|
||||
addBuiltinType(kind, typename, formatOptions, false, true, false, false, 8);
|
||||
break;
|
||||
case TypeOption.Kind.UINT16:
|
||||
addBuiltinType(kind, typename, formatOptions, false, true, false, false, 16);
|
||||
break;
|
||||
case TypeOption.Kind.UINT32:
|
||||
addBuiltinType(kind, typename, formatOptions, false, true, false, false, 32);
|
||||
break;
|
||||
case TypeOption.Kind.UINT64:
|
||||
addBuiltinType(kind, typename, formatOptions, false, true, false, false, 64);
|
||||
break;
|
||||
case TypeOption.Kind.FLOAT32:
|
||||
addBuiltinType(kind, typename, formatOptions, false, true, true, true, 32);
|
||||
break;
|
||||
case TypeOption.Kind.FLOAT64:
|
||||
addBuiltinType(kind, typename, formatOptions, false, true, true, true, 64);
|
||||
break;
|
||||
case TypeOption.Kind.DUCK:
|
||||
addBuiltinType(kind, typename, formatOptions, false, true, true, true, 64);
|
||||
break;
|
||||
default:
|
||||
throw new Error("No default behaviour for " + kind + " as a builtin type, must provide specific behaviour information");
|
||||
}
|
||||
/*
|
||||
* system.addBuiltinType("fencom.stdlib", "bit", new BuiltinTypeBehaviour());
|
||||
|
||||
system.addBuiltinType("fencom.stdlib", "int8", new BuiltinTypeBehaviour.NumberBehaviour(false, true, 8));
|
||||
system.addBuiltinType("fencom.stdlib", "int16", new BuiltinTypeBehaviour.NumberBehaviour(false, true, 16));
|
||||
system.addBuiltinType("fencom.stdlib", "int32", new BuiltinTypeBehaviour.NumberBehaviour(false, true, 32));
|
||||
system.addBuiltinType("fencom.stdlib", "int64", new BuiltinTypeBehaviour.NumberBehaviour(false, true, 64));
|
||||
|
||||
system.addBuiltinType("fencom.stdlib", "uint8", new BuiltinTypeBehaviour.NumberBehaviour(false, false, 8));
|
||||
system.addBuiltinType("fencom.stdlib", "uint16", new BuiltinTypeBehaviour.NumberBehaviour(false, false, 16));
|
||||
system.addBuiltinType("fencom.stdlib", "uint32", new BuiltinTypeBehaviour.NumberBehaviour(false, false, 32));
|
||||
system.addBuiltinType("fencom.stdlib", "uint64", new BuiltinTypeBehaviour.NumberBehaviour(false, false, 64));
|
||||
|
||||
system.addBuiltinType("fencom.stdlib", "float32", new BuiltinTypeBehaviour.NumberBehaviour(true, true, 32));
|
||||
system.addBuiltinType("fencom.stdlib", "float64", new BuiltinTypeBehaviour.NumberBehaviour(true, true, 64));
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
private MetaOrAlias[] addMetaOrAliasArray(MetaOrAlias[] arr, MetaOrAlias ext) {
|
||||
MetaOrAlias[] r = new MetaOrAlias[arr.length + 1];
|
||||
for (int i = 0; i < r.length; i++) {
|
||||
if (i < arr.length) {
|
||||
r[i] = arr[i];
|
||||
} else {
|
||||
r[i] = ext;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
public void addMeta(boolean important, String key, String value) {
|
||||
if (important) {
|
||||
importantMeta = addMetaOrAliasArray(importantMeta, new MetaOrAlias(key, value));
|
||||
} else {
|
||||
otherMeta = addMetaOrAliasArray(otherMeta, new MetaOrAlias(key, value));
|
||||
}
|
||||
}
|
||||
|
||||
public void addAliasType(String aliasName, String targetName) {
|
||||
aliasTypes = addMetaOrAliasArray(aliasTypes, new MetaOrAlias(aliasName, targetName));
|
||||
}
|
||||
|
||||
public void addAliasPackage(String aliasName, String targetName) {
|
||||
aliasPackages = addMetaOrAliasArray(aliasPackages, new MetaOrAlias(aliasName, targetName));
|
||||
}
|
||||
|
||||
public void addMainType(String typeName) {
|
||||
String[] newarr = new String[mainTypes.length + 1];
|
||||
for (int i = 0; i < newarr.length; i++) {
|
||||
if (i < mainTypes.length) {
|
||||
newarr[i] = mainTypes[i];
|
||||
} else {
|
||||
newarr[i] = typeName;
|
||||
}
|
||||
}
|
||||
mainTypes = newarr;
|
||||
}
|
||||
|
||||
public void addDataFile(String packagename, String innername, byte[] data, String typeinfo, String debugname) {
|
||||
DataFile[] newarr = new DataFile[dataFiles.length + 1];
|
||||
for (int i = 0; i < newarr.length; i++) {
|
||||
if (i < dataFiles.length) {
|
||||
newarr[i] = dataFiles[i];
|
||||
} else {
|
||||
newarr[i] = new DataFile(packagename, innername, data, typeinfo, debugname);
|
||||
}
|
||||
}
|
||||
dataFiles = newarr;
|
||||
}
|
||||
|
||||
public void addSource(Source source, boolean referenceOnly) {
|
||||
if (referenceOnly) {
|
||||
Unit[] nsources = new Unit[referencedSources.length + 1];
|
||||
for (int i = 0; i < referencedSources.length; i++) {
|
||||
nsources[i] = referencedSources[i];
|
||||
}
|
||||
nsources[nsources.length - 1] = new Unit(this, source);
|
||||
referencedSources = nsources;
|
||||
} else {
|
||||
Unit[] nsources = new Unit[includedSources.length + 1];
|
||||
for (int i = 0; i < includedSources.length; i++) {
|
||||
nsources[i] = includedSources[i];
|
||||
}
|
||||
nsources[nsources.length - 1] = new Unit(this, source);
|
||||
includedSources = nsources;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompilerSet getNamedElement(int index) {
|
||||
return (CompilerSet) super.getNamedElement(index);
|
||||
}
|
||||
|
||||
public Reporter getReporter() {
|
||||
if (reporter == null) {
|
||||
reporter = new NullReporter();
|
||||
}
|
||||
return reporter;
|
||||
}
|
||||
|
||||
public void setReporter(Reporter reporter) {
|
||||
this.reporter = reporter;
|
||||
}
|
||||
|
||||
public static String pkgname(String fullname) {
|
||||
int l = fullname.searchLast(".");
|
||||
if (l < 0) {
|
||||
return "";
|
||||
} else {
|
||||
return fullname.sub(0, l);
|
||||
}
|
||||
}
|
||||
|
||||
public static String typname(String fullname) {
|
||||
int l = fullname.searchLast(".");
|
||||
if (l < 0) {
|
||||
return "";
|
||||
} else {
|
||||
return fullname.sub(l + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/** Builds the sources, returning true if completed or false otherwise (errors will be reported to the reporter).
|
||||
*
|
||||
* @return true if completed successfully, false otherwise.
|
||||
*/
|
||||
public boolean build() {
|
||||
int i; // Reused for many small top-level loops.
|
||||
/*
|
||||
getReporter().note("STAGE", "Scanning referenced sources");
|
||||
for (i = 0; i < referencedSources.length; i++) {
|
||||
getReporter().note("STAGE-PART", referencedSources[i].getFilename());
|
||||
referencedSources[i].scan();
|
||||
}
|
||||
getReporter().note("STAGE", "Scanning included sources");
|
||||
for (i = 0; i < includedSources.length; i++) {
|
||||
getReporter().note("STAGE-PART", includedSources[i].getFilename());
|
||||
includedSources[i].scan();
|
||||
}
|
||||
*/
|
||||
getReporter().note("STAGE", "Parsing referenced sources");
|
||||
for (i = 0; i < referencedSources.length; i++) {
|
||||
getReporter().note("STAGE-PART", referencedSources[i].getFilename());
|
||||
referencedSources[i].parse();
|
||||
try {
|
||||
getReporter().note("CACHE", "Using cache filename " + referencedSources[i].getCacheName() + " for " + referencedSources[i].getFilename());
|
||||
if (referencedSources[i].updateCache()) {
|
||||
getReporter().note("CACHE", "Updated cache");
|
||||
} else {
|
||||
getReporter().note("CACHE", "Skipped updating cache");
|
||||
}
|
||||
} catch (Error e) {
|
||||
getReporter().note("CACHE", "Cache failed for " + referencedSources[i].getFilename());
|
||||
e.log();
|
||||
}
|
||||
}
|
||||
getReporter().note("STAGE", "Parsing included sources");
|
||||
for (i = 0; i < includedSources.length; i++) {
|
||||
getReporter().note("STAGE-PART", includedSources[i].getFilename());
|
||||
includedSources[i].parse();
|
||||
try {
|
||||
getReporter().note("CACHE", "Using cache filename " + includedSources[i].getCacheName() + " for " + includedSources[i].getFilename());
|
||||
if (includedSources[i].updateCache()) {
|
||||
getReporter().note("CACHE", "Updated cache");
|
||||
} else {
|
||||
getReporter().note("CACHE", "Skipped updating cache");
|
||||
}
|
||||
} catch (Error e) {
|
||||
getReporter().note("CACHE", "Cache failed for " + includedSources[i].getFilename());
|
||||
e.log();
|
||||
}
|
||||
}
|
||||
getReporter().note("STAGE", "Checking referenced sources");
|
||||
int totalerrors = 0;
|
||||
for (i = 0; i < referencedSources.length; i++) {
|
||||
int e = referencedSources[i].checkErrors(errorVerbosity);
|
||||
if (e != 0) {
|
||||
getReporter().note("ERRORS", "Found " + e + " errors in '" + referencedSources[i].getFilename() + "'");
|
||||
}
|
||||
totalerrors += e;
|
||||
}
|
||||
getReporter().note("STAGE", "Checking included sources");
|
||||
int ngood = 0;
|
||||
int nbad = 0;
|
||||
for (i = 0; i < includedSources.length; i++) {
|
||||
int e = includedSources[i].checkErrors(errorVerbosity);
|
||||
if (e != 0) {
|
||||
nbad++;
|
||||
getReporter().note("ERRORS", "Found " + e + " errors in '" + includedSources[i].getFilename() + "'");
|
||||
} else {
|
||||
ngood++;
|
||||
}
|
||||
totalerrors += e;
|
||||
}
|
||||
|
||||
double ratiogood = ((double) ngood) / ((double) ngood + nbad);
|
||||
int percentgood = (int) (ratiogood * 100);
|
||||
|
||||
getReporter().note("SUMMARY", "" + ngood + " good files and " + nbad + " bad files (" + percentgood + "% good)");
|
||||
|
||||
if (totalerrors != 0) {
|
||||
getReporter().note("TERMINATED", "Scanning/parsing/checking of sources resulted in " + totalerrors + " errors");
|
||||
return false;
|
||||
}
|
||||
|
||||
SystemModel system = new SystemModel();
|
||||
|
||||
getReporter().note("STAGE", "Configuring runtime types");
|
||||
|
||||
String core = "kebab0.core";
|
||||
|
||||
system.addBuiltinType(core, "bit", new BuiltinTypeBehaviour());
|
||||
|
||||
system.addBuiltinType(core, "duck", new BuiltinTypeBehaviour.DuckBehaviour());
|
||||
|
||||
system.addBuiltinType(core, "int8", new BuiltinTypeBehaviour.NumberBehaviour(false, true, 8));
|
||||
system.addBuiltinType(core, "int16", new BuiltinTypeBehaviour.NumberBehaviour(false, true, 16));
|
||||
system.addBuiltinType(core, "int32", new BuiltinTypeBehaviour.NumberBehaviour(false, true, 32));
|
||||
system.addBuiltinType(core, "int64", new BuiltinTypeBehaviour.NumberBehaviour(false, true, 64));
|
||||
|
||||
system.addBuiltinType(core, "uint8", new BuiltinTypeBehaviour.NumberBehaviour(false, false, 8));
|
||||
system.addBuiltinType(core, "uint16", new BuiltinTypeBehaviour.NumberBehaviour(false, false, 16));
|
||||
system.addBuiltinType(core, "uint32", new BuiltinTypeBehaviour.NumberBehaviour(false, false, 32));
|
||||
system.addBuiltinType(core, "uint64", new BuiltinTypeBehaviour.NumberBehaviour(false, false, 64));
|
||||
|
||||
system.addBuiltinType(core, "float32", new BuiltinTypeBehaviour.NumberBehaviour(true, true, 32));
|
||||
system.addBuiltinType(core, "float64", new BuiltinTypeBehaviour.NumberBehaviour(true, true, 64));
|
||||
|
||||
system.addBuiltinType(core, "pointer", new BuiltinTypeBehaviour());
|
||||
//system.addBuiltinType(core, "word", new BuiltinTypeBehaviour());
|
||||
|
||||
/*for (i = 0; i < typeOptions.length; i++) {
|
||||
TypeOption o = typeOptions[i];
|
||||
if (o.isBuiltin) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}*/
|
||||
system.setTypeOptions(typeOptions);
|
||||
|
||||
/* The built-in types should be quite specific. For general-purpose use, aliases comparable to
|
||||
* standard C/D/Java/C# types are provided. These just point to the underlying built-in types.
|
||||
*/
|
||||
system.addAliasType(core, "boolean", core, "bit");
|
||||
system.addAliasType(core, "byte", core, "int8");
|
||||
system.addAliasType(core, "short", core, "int16");
|
||||
system.addAliasType(core, "char", core, "uint16");
|
||||
system.addAliasType(core, "int", core, "int32");
|
||||
system.addAliasType(core, "long", core, "int64");
|
||||
system.addAliasType(core, "float", core, "float32");
|
||||
system.addAliasType(core, "double", core, "float64");
|
||||
|
||||
for (i = 0; i < aliasTypes.length; i++) {
|
||||
MetaOrAlias a = aliasTypes[i];
|
||||
system.addAliasType(pkgname(a.key), typname(a.key), pkgname(a.value), typname(a.value));
|
||||
}
|
||||
|
||||
for (i = 0; i < aliasPackages.length; i++) {
|
||||
MetaOrAlias a = aliasPackages[i];
|
||||
system.addAliasPackage(a.key, a.value);
|
||||
}
|
||||
|
||||
/*
|
||||
system.addGlobalImport("fencom.stdlib");
|
||||
system.addGlobalImport("java.lang");
|
||||
*/
|
||||
for (i = 0; i < globalImports.length; i++) {
|
||||
if (globalImports[i].endsWith("*")) {
|
||||
system.addGlobalImport(pkgname(globalImports[i]));
|
||||
} else {
|
||||
system.addGlobalImport(pkgname(globalImports[i]), typname(globalImports[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if (arrayLengthNames != null) {
|
||||
getReporter().note("STAGE", "Overriding some magical options");
|
||||
system.setArrayLengthNames(arrayLengthNames);
|
||||
}
|
||||
|
||||
getReporter().note("STAGE", "Adding referenced sources");
|
||||
for (i = 0; i < referencedSources.length; i++) {
|
||||
system.addUnit(referencedSources[i], false);
|
||||
}
|
||||
getReporter().note("STAGE", "Adding included sources");
|
||||
for (i = 0; i < includedSources.length; i++) {
|
||||
system.addUnit(includedSources[i], true);
|
||||
}
|
||||
|
||||
getReporter().note("STAGE", "Checking for initial errors");
|
||||
if (system.countErrors() != 0) {
|
||||
getReporter().note("TERMINATED", "Unpacking into internal model resulted in " + system.countErrors() + " errors");
|
||||
}
|
||||
|
||||
//system.dump(getReporter());
|
||||
|
||||
int expandStage = 1;
|
||||
boolean keepExpanding = true;
|
||||
while (keepExpanding) {
|
||||
getReporter().note("STAGE", "Expanding internal model (phase " + expandStage + ")");
|
||||
int nexpanded = system.expand();
|
||||
getReporter().note("NOTE", "Expanded " + nexpanded + " items");
|
||||
//system.dump(getReporter());
|
||||
if (system.countErrors() != 0) {
|
||||
keepExpanding = false;
|
||||
getReporter().note("TERMINATED", "Expanding internal model resulted in " + system.countErrors() + " errors");
|
||||
//return false;
|
||||
}
|
||||
if (nexpanded == 0) {
|
||||
keepExpanding = false;
|
||||
}
|
||||
expandStage++;
|
||||
}
|
||||
|
||||
int resolveStage = 1;
|
||||
boolean keepResolving = true;
|
||||
int maxErrorRetries = 100;
|
||||
int errorRetries = 0;
|
||||
int maxNoExpandRetries = 100;
|
||||
while (keepResolving) {
|
||||
getReporter().note("STAGE", "Resolving types (phase " + resolveStage + ")");
|
||||
int nexpanded = system.resolveTypes();
|
||||
getReporter().note("NOTE", "Resolved " + nexpanded + " items");
|
||||
//system.dump(getReporter());
|
||||
if (system.countErrors() != 0) {
|
||||
//if (errorRetries > maxErrorRetries) {
|
||||
keepResolving = false;
|
||||
getReporter().note("TERMINATED", "Resolving types resulted in " + system.countErrors() + " errors");
|
||||
//return false;
|
||||
/*} else {
|
||||
getReporter().note("RETRYING", "Failed to resolve some types, I wiil retry assuming further expansion is necessary to find them");
|
||||
system.deleteErrors();
|
||||
errorRetries++;
|
||||
}*/
|
||||
}
|
||||
if (nexpanded == 0) {
|
||||
getReporter().note("NOT-RETRYING", "Maximum number of internal no-expand retries exceded");
|
||||
keepResolving = false;
|
||||
}
|
||||
resolveStage++;
|
||||
}
|
||||
|
||||
for (int tmp = 0; tmp < 10; tmp++) {
|
||||
getReporter().note("NOTE", "Extra check stage " + tmp);
|
||||
if (system.resolveTypes() != 0) {
|
||||
getReporter().note("WARNING", "Extra expansion is necessary???");
|
||||
}
|
||||
}
|
||||
//system.dump(getReporter());
|
||||
|
||||
if (checkErrors() != 0) {
|
||||
getReporter().note("FAILED-IN", "Seems to have failed in the type-expansion stage");
|
||||
return false;
|
||||
}
|
||||
|
||||
resolveStage = 1;
|
||||
keepResolving = true;
|
||||
while (keepResolving) {
|
||||
getReporter().note("STAGE", "Resolving expressions (phase " + resolveStage + ")");
|
||||
int nexpanded = system.resolveExpressions(false); // NOTE: The parameter controls whether or not references are checked too
|
||||
getReporter().note("NOTE", "Resolved " + nexpanded + " items");
|
||||
//system.dump(getReporter());
|
||||
if (system.countErrors() != 0) {
|
||||
keepResolving = false;
|
||||
getReporter().note("TERMINATED", "Resolving expressions resulted in " + system.countErrors() + " errors");
|
||||
//return false;
|
||||
}
|
||||
if (nexpanded == 0) {
|
||||
keepResolving = false;
|
||||
}
|
||||
resolveStage++;
|
||||
}
|
||||
|
||||
if (checkErrors() != 0) {
|
||||
getReporter().note("FAILED-IN", "Seems to have failed in the expression-reslolving stage");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This isn't finished yet (disabled for now in favour of a cleaner/slower expression resolution stage)
|
||||
CTarget.transpile(system, "foo.h", new LineOutput() {
|
||||
|
||||
@Override
|
||||
public void line(String line) {
|
||||
System.err.println("HDR> " + line);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endOfFile() {
|
||||
System.err.println("HDR END");
|
||||
}
|
||||
}, new LineOutput() {
|
||||
|
||||
@Override
|
||||
public void line(String line) {
|
||||
System.err.println("SRC> " + line);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endOfFile() {
|
||||
System.err.println("SRC END");
|
||||
}
|
||||
});*/
|
||||
|
||||
if (getTarget() == null) {
|
||||
getReporter().note("ABORTED", "No target to write to");
|
||||
return false;
|
||||
} else {
|
||||
getTarget().setSystem(system);
|
||||
int total = 0;
|
||||
String[] pkgs = system.getPackageNames();
|
||||
for (i = 0; i < providesDepends.length; i++) {
|
||||
ProvidesOrDepends x = providesDepends[i];
|
||||
getReporter().note("REGISTERING", (x.provides ? "provides" : "depends") + " name '" + x.name + "' version '" + x.version + "'");
|
||||
getTarget().visitProvidesOrDepends(x);
|
||||
}
|
||||
int mainTypesFound = 0;
|
||||
for (i = 0; i < pkgs.length; i++) {
|
||||
PackageModel p = system.getPackage(pkgs[i]);
|
||||
String[] typs = p.getTypeNames();
|
||||
for (int j = 0; j < typs.length; j++) {
|
||||
TypeModel m = p.getType(typs[j]);
|
||||
MethodModel[] constrs = m.getInstanceConstructors();
|
||||
//for (int x = 0; x < constrs.length; x++) {
|
||||
// Log.line("Type " + m.fullName() + "[" + typs[j] + "] has constr #" + x + ": " + constrs[x].toString());
|
||||
//}
|
||||
if (m instanceof UserTypeModel && m.existsAtRuntime() && !m.isReferenceOnly()) {
|
||||
String name = m.fullName();
|
||||
boolean isMain = false;
|
||||
getReporter().note("COMPILING", "#" + total + ": " + name);
|
||||
for (int x = 0; x < mainTypes.length; x++) {
|
||||
if (name.equals(mainTypes[x])) {
|
||||
mainTypesFound++;
|
||||
isMain = true;
|
||||
getReporter().note("NOTE", "Adding " + name + " to main list");
|
||||
}
|
||||
}
|
||||
getTarget().visitType((UserTypeModel) m, isMain);
|
||||
total++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mainTypesFound != mainTypes.length) {
|
||||
getReporter().note("WARNING", "Couldn't find main types (expecting " + mainTypes.length + " found " + mainTypesFound);
|
||||
}
|
||||
for (i = 0; i < dataFiles.length; i++) {
|
||||
getReporter().note("INSERTING", "#" + total + ": " + dataFiles[i].packagename + "." + dataFiles[i].innername);
|
||||
getTarget().visitDataFile(dataFiles[i]);
|
||||
total++;
|
||||
}
|
||||
for (i = 0; i < importantMeta.length; i++) {
|
||||
getTarget().visitMeta(true, importantMeta[i].key, importantMeta[i].value);
|
||||
}
|
||||
for (i = 0; i < otherMeta.length; i++) {
|
||||
getTarget().visitMeta(false, otherMeta[i].key, otherMeta[i].value);
|
||||
}
|
||||
for (i = 0; i < typeOptions.length; i++) {
|
||||
getTarget().visitTypeOption(typeOptions[i]);
|
||||
}
|
||||
if (total > 0) {
|
||||
if (checkErrors() != 0) {
|
||||
getReporter().note("FINISHING", "Producing (WITH ERRORS) a total of " + total + " type-level objects: " + getTarget().quickReport());
|
||||
getTarget().finish();
|
||||
getReporter().note("PARTIAL-SUCCESS", "Target has been produced (WITH ERRORS).");
|
||||
return false;
|
||||
} else {
|
||||
getReporter().note("FINISHING", "Producing a total of " + total + " toplevels: " + getTarget().quickReport());
|
||||
Log.line("In CompilerWorld");
|
||||
getTarget().finish();
|
||||
getReporter().note("SUCCESS", "Target has been produced.");
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
getReporter().note("ABORTED", "Producing empty target.");
|
||||
getTarget().finish();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int checkErrors() {
|
||||
|
||||
getReporter().note("CHECK", "Checking referenced sources for errors");
|
||||
int terrors = 0;
|
||||
for (int i = 0; i < referencedSources.length; i++) {
|
||||
int e = referencedSources[i].checkErrors(errorVerbosity);
|
||||
if (e != 0) {
|
||||
getReporter().note("ERRORS", "Found " + e + " errors in '" + referencedSources[i].getFilename() + "'");
|
||||
}
|
||||
terrors += e;
|
||||
}
|
||||
|
||||
if (terrors != 0) {
|
||||
getReporter().note("FAILED", "Checking of referenced sources resulted in " + terrors + " errors");
|
||||
return terrors;
|
||||
}
|
||||
|
||||
getReporter().note("CHECK", "Checking included sources for errors");
|
||||
for (int i = 0; i < includedSources.length; i++) {
|
||||
int e = includedSources[i].checkErrors(errorVerbosity);
|
||||
if (e != 0) {
|
||||
getReporter().note("ERRORS", "Found " + e + " errors in '" + includedSources[i].getFilename() + "'");
|
||||
}
|
||||
terrors += e;
|
||||
}
|
||||
|
||||
// Some random syntax tests were inserted here just to see how they behave
|
||||
// on the plaform which shall not be named:
|
||||
//String[] foo = {"foo","bar"};
|
||||
//Object[] bar = foo;
|
||||
//int[] x = {1,2,3};
|
||||
//long[] y = x;
|
||||
// Some weird behaviour I found in some random code (binary operators on booleans):
|
||||
//int wtf1 = 0, wtf2 = 0, wtf3 = 0, wtf4 = 0;
|
||||
//getReporter().note("TEST", "" + (wtf1 < wtf2-1 & (wtf1 != wtf3-1 | wtf4 == 0)));
|
||||
|
||||
if (terrors != 0) {
|
||||
getReporter().note("FAILED", "Checking of included sources resulted in " + terrors + " errors");
|
||||
return terrors;
|
||||
}
|
||||
|
||||
|
||||
return terrors;
|
||||
}
|
||||
|
||||
public Language getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
public void setLanguage(Language l) {
|
||||
language = l;
|
||||
}
|
||||
}
|
17
slangc/api/DataFile.sauce
Normal file
17
slangc/api/DataFile.sauce
Normal file
@ -0,0 +1,17 @@
|
||||
package slangc.api;
|
||||
|
||||
public class DataFile {
|
||||
String packagename;
|
||||
String innername;
|
||||
byte[] data;
|
||||
String typeinfo;
|
||||
String debugname;
|
||||
public DataFile(String packagename, String innername, byte[] data, String typeinfo, String debugname) {
|
||||
this.packagename = packagename;
|
||||
this.innername = innername;
|
||||
this.data = data;
|
||||
this.typeinfo = typeinfo;
|
||||
this.debugname = debugname;
|
||||
}
|
||||
|
||||
}
|
12
slangc/api/MetaOrAlias.sauce
Normal file
12
slangc/api/MetaOrAlias.sauce
Normal file
@ -0,0 +1,12 @@
|
||||
package slangc.api;
|
||||
|
||||
public class MetaOrAlias {
|
||||
public final String key;
|
||||
public final String value;
|
||||
|
||||
public MetaOrAlias(String key, String value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
34
slangc/api/NullReporter.sauce
Normal file
34
slangc/api/NullReporter.sauce
Normal file
@ -0,0 +1,34 @@
|
||||
package slangc.api;
|
||||
|
||||
public class NullReporter implements Reporter {
|
||||
|
||||
public NullReporter() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public void loadingSource(String filename, boolean included) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void loadingFile(String filename, boolean included) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void loadingReferencedSet(String filename) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void finishedLoading(int referencedSources, int referencedFiles, int referencedSets, int includedSources,
|
||||
int includedFiles) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void note(String topic, String text) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
17
slangc/api/ProvidesOrDepends.sauce
Normal file
17
slangc/api/ProvidesOrDepends.sauce
Normal file
@ -0,0 +1,17 @@
|
||||
package slangc.api;
|
||||
|
||||
public class ProvidesOrDepends {
|
||||
public final boolean provides;
|
||||
public final String name;
|
||||
public final String version;
|
||||
|
||||
public ProvidesOrDepends(boolean provides, String name, String version) {
|
||||
super();
|
||||
this.provides = provides;
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
10
slangc/api/Reporter.sauce
Normal file
10
slangc/api/Reporter.sauce
Normal file
@ -0,0 +1,10 @@
|
||||
package slangc.api;
|
||||
|
||||
public interface Reporter {
|
||||
public void note(String topic, String text);
|
||||
public void loadingSource(String filename, boolean included);
|
||||
public void loadingFile(String filename, boolean included);
|
||||
public void loadingReferencedSet(String filename);
|
||||
public void finishedLoading(int referencedSources, int referencedFiles, int referencedSets, int includedSources, int includedFiles);
|
||||
|
||||
}
|
93
slangc/api/TypeOption.sauce
Normal file
93
slangc/api/TypeOption.sauce
Normal file
@ -0,0 +1,93 @@
|
||||
package slangc.api;
|
||||
|
||||
import slangc.bytecode.TypeSignature;
|
||||
|
||||
public class TypeOption {
|
||||
/** Note the first 16 must match up to BytecodeInstructionWriter.StackType. */
|
||||
public static enum Kind {
|
||||
/* #0-#3 are used for special types (these are not valid in all scenarios). */
|
||||
UNINITIALISED,
|
||||
INVALID,
|
||||
DUCK,
|
||||
VOID,
|
||||
/* #4 is the object type. */
|
||||
OBJECT,
|
||||
/* #5-#7 are the basic non-integer primitives. */
|
||||
BIT,
|
||||
FLOAT32,
|
||||
FLOAT64,
|
||||
|
||||
/* #8-#15 are the basic integer primitives. */
|
||||
INT8,
|
||||
INT16,
|
||||
INT32,
|
||||
INT64,
|
||||
UINT8,
|
||||
UINT16,
|
||||
UINT32,
|
||||
UINT64,
|
||||
|
||||
/* #16-#31 are the other standard runtime types. */
|
||||
MAGIC,
|
||||
TYPE,
|
||||
STRING,
|
||||
ENUMBASE,
|
||||
ARRAYBASE,
|
||||
INSTANCECONSTRUCTOR,
|
||||
STATICCONSTRUCTOR,
|
||||
INSTANCEFIELD,
|
||||
INSTANCEMETHOD,
|
||||
STATICFIELD,
|
||||
STATICMETHOD,
|
||||
INTERFACEMETHOD,
|
||||
BYTECODEFILE,
|
||||
LOADER,
|
||||
THREAD,
|
||||
DEVICEHANDLE
|
||||
}
|
||||
|
||||
public final Kind kind;
|
||||
public final String typeName;
|
||||
public final String formatopt;
|
||||
|
||||
public final boolean isBuiltin;
|
||||
public final boolean isDuck;
|
||||
public final boolean isNumber;
|
||||
public final boolean isFloat;
|
||||
public final boolean isSigned;
|
||||
public final int nbits;
|
||||
|
||||
public TypeSignature getTypeSignature() {
|
||||
if (kind == Kind.VOID) {
|
||||
return TypeSignature.VOID;
|
||||
} else {
|
||||
return new TypeSignature(CompilerWorld.pkgname(typeName), CompilerWorld.typname(typeName));
|
||||
}
|
||||
}
|
||||
|
||||
public TypeOption(Kind kind, String value, String formatopt) {
|
||||
super();
|
||||
this.kind = kind;
|
||||
this.typeName = value;
|
||||
this.formatopt = formatopt;
|
||||
this.isBuiltin = false;
|
||||
this.isDuck = false;
|
||||
this.isNumber = false;
|
||||
this.isFloat = false;
|
||||
this.isSigned = false;
|
||||
this.nbits = -1;
|
||||
}
|
||||
|
||||
public TypeOption(Kind kind, String value, String formatopt, boolean isBuiltin, boolean isDuck, boolean isNumber, boolean isFloat, boolean isSigned, int nbits) {
|
||||
this.kind = kind;
|
||||
this.typeName = value;
|
||||
this.formatopt = formatopt;
|
||||
this.isBuiltin = isBuiltin;
|
||||
this.isDuck = isDuck;
|
||||
this.isNumber = isNumber;
|
||||
this.isFloat = isFloat;
|
||||
this.isSigned = isSigned;
|
||||
this.nbits = -1;
|
||||
}
|
||||
|
||||
}
|
245
slangc/api/Unit.sauce
Normal file
245
slangc/api/Unit.sauce
Normal file
@ -0,0 +1,245 @@
|
||||
package slangc.api;
|
||||
|
||||
import slang.data.Mappable;
|
||||
import slang.streams.SyncOutput;
|
||||
import slang.streams.SyncInput;
|
||||
|
||||
import slangc.parser.Annotation;
|
||||
import slangc.parser.AnnotationType;
|
||||
import slangc.parser.Branch;
|
||||
import slangc.parser.LocationAnnotation;
|
||||
import slangc.parser.ErrorAnnotation;
|
||||
import slangc.parser.NoteAnnotation;
|
||||
import slangc.parser.LocationType;
|
||||
import slangc.parser.Node;
|
||||
import slangc.parser.Parse;
|
||||
import slangc.parser.Scan;
|
||||
import slangc.parser.Source;
|
||||
import slangc.parser.Token;
|
||||
import slangc.parser.WarningType;
|
||||
|
||||
/**
|
||||
* Holds all of the information for a unit (sourceFile file) and abstracts away the semantics of scanning/parsing/checking them.
|
||||
* @author Zak
|
||||
*
|
||||
*/
|
||||
public class Unit {
|
||||
private CompilerWorld world;
|
||||
private Source source;
|
||||
private Scan scan = null;
|
||||
private Branch parse = null;
|
||||
|
||||
public Unit(CompilerWorld world, Source source) {
|
||||
this.world = world;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public CompilerWorld getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public Source getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public String getFilename() {
|
||||
return getSource().getFilename();
|
||||
}
|
||||
|
||||
int hashCache = -1;
|
||||
public int getCacheHash() {
|
||||
if (hashCache < 0) {
|
||||
hashCache = Mappable.nonNegativeHashOf(getSource().getString(0, getSource().getIndexLength()));
|
||||
}
|
||||
return hashCache;
|
||||
}
|
||||
|
||||
public boolean updateCache() {
|
||||
try {
|
||||
Branch b = parse();
|
||||
// TODO: Check if needs updating here
|
||||
SyncOutput<byte> o = world.getCacheManager().getOutput(getCacheName());
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
b.dumpBinary(o);
|
||||
o.close();
|
||||
return true;
|
||||
} catch (duck d) {
|
||||
Log.line("WARNING: Updating cache failed with error");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String getCacheName() {
|
||||
return "." + getCacheHash() + "." + getSource().getIndexLength() + ".cache";
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
Branch pkg = (Branch) parse().getSubnode(0);
|
||||
if (pkg == null) {
|
||||
return "defpkg"; //throw new Error("Invalid package format");
|
||||
}
|
||||
pkg = (Branch) pkg.getSubnode(1);
|
||||
if (pkg == null) {
|
||||
throw new Error("Invalid package format");
|
||||
}
|
||||
String name = "";
|
||||
for (int i = 0; i < pkg.countSubnodes(); i++) {
|
||||
Branch sub = (Branch) pkg.getSubnode(i);
|
||||
if (sub == null) {
|
||||
throw new Error("Invalid package format");
|
||||
}
|
||||
Token token = (Token) sub.getSubnode(0);
|
||||
if (token == null) {
|
||||
throw new Error("Invalid package format");
|
||||
}
|
||||
name += token.getSnippet().getSource();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public Scan scan() {
|
||||
if (scan == null) {
|
||||
scan = new Scan(world.getLanguage(), source);
|
||||
//scan.scanPedantic();
|
||||
scan.scanQuick();
|
||||
}
|
||||
|
||||
return scan;
|
||||
}
|
||||
|
||||
public Branch loadCache(SyncInput<byte> inp) {
|
||||
scan = new Scan(world.getLanguage(), source);
|
||||
parse = (Branch) Node.loadBinary(scan, inp);
|
||||
inp.close();
|
||||
_wasCached = true;
|
||||
return parse;
|
||||
}
|
||||
|
||||
private boolean _wasCached = false;
|
||||
|
||||
public boolean wasCached() {
|
||||
return _wasCached;
|
||||
}
|
||||
|
||||
public Branch parse() {
|
||||
if (parse == null) {
|
||||
SyncInput<byte> cacheIn = world.getCacheManager().getInput(getCacheName());
|
||||
if (cacheIn != null) {
|
||||
//Log.line("Loading from cache...");
|
||||
return loadCache(cacheIn);
|
||||
}
|
||||
//Log.line("Not cached...");
|
||||
Scan s = scan();
|
||||
Parse p = new Parse();
|
||||
parse = (Branch) p.parseUnit(s);
|
||||
}
|
||||
|
||||
return parse;
|
||||
}
|
||||
|
||||
private Token checkRecursively(Branch b, Token p) {
|
||||
if (!Node.mightHaveErrors && !Node.mightHaveWarnings) {
|
||||
return p;
|
||||
}
|
||||
if (p != null && b.countAnnotations(AnnotationType.LOCATION) == 0) {
|
||||
b.annotate(new LocationAnnotation(LocationType.AFTER, p));
|
||||
}
|
||||
for (int i = 0; i < b.countSubnodes(); i++) {
|
||||
Node n = b.getSubnode(i);
|
||||
if (n instanceof Token) {
|
||||
p = (Token) n;
|
||||
p.annotate(new LocationAnnotation(LocationType.AROUND, p));
|
||||
} else if (n == null) {
|
||||
b.annotate(WarningType.INTERNAL_WARNING, "Had a null member");
|
||||
} else {
|
||||
p = checkRecursively((Branch) n, p);
|
||||
}
|
||||
}
|
||||
if (p != null && b.countAnnotations(AnnotationType.LOCATION) == 0) {
|
||||
b.annotate(new LocationAnnotation(LocationType.AROUND, p));
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
public int checkErrors(int verbosity) {
|
||||
int nerrors = 0;
|
||||
|
||||
Branch p = parse();
|
||||
|
||||
checkRecursively(p, null);
|
||||
|
||||
//getWorld().getReporter().note("CHECKING", getFilename());
|
||||
|
||||
//getWorld().getReporter().note("CHECKING", "File '" + getFilename() + "' reports package as '" + getPackageName() + "'");
|
||||
|
||||
nerrors += p.countErrorsRecursively();
|
||||
|
||||
if (nerrors != 0) {
|
||||
getWorld().getReporter().note("ERRORS", "Found " + nerrors + " errors in '" + getFilename() + "', dumping AST:");
|
||||
dump(getWorld().getReporter(), parse(), verbosity);
|
||||
}
|
||||
|
||||
return nerrors;
|
||||
}
|
||||
|
||||
private static void dump(Reporter out, Node n, int verbosity) {
|
||||
dump(out, n, "", verbosity < 5 ? "" : " ", verbosity);
|
||||
}
|
||||
|
||||
private static void dump(Reporter out, Node n, String curindent, String subindent, int verbosity) {
|
||||
if (n instanceof Branch) {
|
||||
dumpBranch(out, (Branch) n, curindent, subindent, verbosity);
|
||||
} else if (n instanceof Token) {
|
||||
dumpToken(out, (Token) n, curindent, subindent, verbosity);
|
||||
} else if (n instanceof Annotation) {
|
||||
dumpAnnotation(out, (Annotation) n, curindent, subindent, verbosity);
|
||||
} else if (n == null) {
|
||||
out.note("DUMP", curindent + "-! UH-OH !- null");
|
||||
} else {
|
||||
out.note("DUMP", curindent + "-! TO-DO !- code to dump " + n.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static void dumpAnnotations(Reporter out, Node n, String curindent, String subindent, int verbosity) {
|
||||
for (int i = 0; i < n.countAnnotations(); i++) {
|
||||
dump(out, n.getAnnotation(i), curindent + subindent, subindent, verbosity);
|
||||
}
|
||||
}
|
||||
|
||||
private static void dumpBranch(Reporter out, Branch b, String curindent, String subindent, int verbosity) {
|
||||
if (verbosity < 10 && b.countErrorsRecursively() == 0) {
|
||||
if (verbosity > 2) out.note("DUMP", curindent + "-> " + b.getNodeType().name() + " (...)");
|
||||
return;
|
||||
}
|
||||
if (verbosity >= 5 || b.countErrorsHere() > 0) {
|
||||
if (verbosity > 2) out.note("DUMP", curindent + "-> " + b.getNodeType());
|
||||
dumpAnnotations(out, b, curindent, subindent, verbosity);
|
||||
}
|
||||
for (int i = 0; i < b.countSubnodes(); i++) {
|
||||
dump(out, b.getSubnode(i), curindent + subindent, subindent, verbosity);
|
||||
}
|
||||
}
|
||||
|
||||
private static void dumpToken(Reporter out, Token t, String curindent, String subindent, int verbosity) {
|
||||
if (verbosity >= 5) {
|
||||
out.note("DUMP", curindent + "-. " + t);
|
||||
dumpAnnotations(out, t, curindent, subindent, verbosity);
|
||||
}
|
||||
}
|
||||
|
||||
private static void dumpAnnotation(Reporter out, Annotation a, String curindent, String subindent, int verbosity) {
|
||||
if (a instanceof ErrorAnnotation) {
|
||||
out.note("DUMP", curindent + "-! " + ((ErrorAnnotation) a).getErrorType().name());
|
||||
} else if (a instanceof NoteAnnotation) {
|
||||
out.note("DUMP", curindent + "-+ " + ((NoteAnnotation) a).getText());
|
||||
} else if (a instanceof LocationAnnotation) {
|
||||
out.note("DUMP", curindent + "-- " + ((LocationAnnotation) a).niceString());
|
||||
} else {
|
||||
out.note("DUMP", curindent + "-+ " + a.toString());
|
||||
}
|
||||
dumpAnnotations(out, a, curindent, subindent, verbosity);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user