767 lines
26 KiB
Plaintext
767 lines
26 KiB
Plaintext
|
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;
|
||
|
}
|
||
|
}
|