379 lines
13 KiB
Plaintext
379 lines
13 KiB
Plaintext
package slangc.model;
|
|
|
|
import slang.data.ComparisonOp;
|
|
import slang.data.List;
|
|
import slang.data.Map;
|
|
import slangc.api.CompilerWorld;
|
|
import slangc.api.Reporter;
|
|
import slangc.api.TypeOption;
|
|
import slangc.api.Unit;
|
|
import slangc.bytecode.TypeSignature;
|
|
|
|
public class SystemModel {
|
|
//Map<String,SourceModel> sources = new Map<String, SourceModel>();
|
|
//Map<String,TypeModel> types = new Map<String, TypeModel>();
|
|
Map<String,PackageModel> packages = new Map<String, PackageModel>();
|
|
Map<String,PackageModel> packageAliases = new Map<String, PackageModel>();
|
|
List<ImportModel> globalImports = new List<ImportModel>();
|
|
CombinedImportModel combinedGlobalImports = null;
|
|
TypeOption[] typeOptions;
|
|
|
|
private String defaultBasePackage = "kebab0.base"; //"rt";
|
|
private String defaultBaseType = "Object";
|
|
|
|
private String defaultTypePackage = "kebab0.base"; //"rt";
|
|
private String defaultTypeType = "Class";
|
|
|
|
private String defaultStringPackage = "kebab0.base"; //"rt";
|
|
private String defaultStringType = "String";
|
|
|
|
private String defaultBooleanPackage = "kebab0.core"; //"rt";
|
|
private String defaultBooleanType = "bit";
|
|
|
|
private String defaultInt32Package = "kebab0.core"; //"rt";
|
|
private String defaultInt32Type = "int32";
|
|
|
|
private String defaultInt64Package = "kebab0.core"; //"rt";
|
|
private String defaultInt64Type = "int64";
|
|
|
|
private String defaultFloat32Package = "kebab0.core"; //"rt";
|
|
private String defaultFloat32Type = "float32";
|
|
|
|
private String defaultFloat64Package = "kebab0.core"; //"rt";
|
|
private String defaultFloat64Type = "float64";
|
|
|
|
private String defaultDuckPackage = "kebab0.core";
|
|
private String defaultDuckType = "duck";
|
|
|
|
private String defaultVoidPackage = "kebab0.core";
|
|
private String defaultVoidType = "void";
|
|
|
|
private String[] arrayLengthNames = new String[] {"length"};
|
|
|
|
public void setArrayLengthNames(String[] names) {
|
|
arrayLengthNames = names;
|
|
}
|
|
|
|
public String[] getArrayLengthNames() {
|
|
return arrayLengthNames;
|
|
}
|
|
|
|
public boolean isArrayLengthName(String n) {
|
|
for (int i = 0; i < arrayLengthNames.length; i++) {
|
|
if (arrayLengthNames[i].equals(n)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public SourceModel addUnit(Unit unit, boolean isIncluded) {
|
|
//Branch u = unit.parse();
|
|
return getOrCreatePackage(unit.getPackageName(), true).addSource(unit.getFilename(), unit.parse(), isIncluded);
|
|
/*int count = u.countSubnodes();
|
|
for (int i = 0; i < count; i++) {
|
|
Node n = u.getSubnode(i);
|
|
Log.line("Got a '" + n.getNodeType() + "'");
|
|
}*/
|
|
}
|
|
|
|
public PackageImportModel addGlobalImport(String packageName) {
|
|
PackageImportModel m = new PackageImportModel(this, true, packageName);
|
|
combinedGlobalImports = null;
|
|
globalImports.append(m);
|
|
return m;
|
|
}
|
|
|
|
public TypeImportModel addGlobalImport(String packageName, String typeName) {
|
|
TypeImportModel m = new TypeImportModel(this, packageName, typeName);
|
|
combinedGlobalImports = null;
|
|
globalImports.append(m);
|
|
return m;
|
|
}
|
|
|
|
public CombinedImportModel getGlobalImports() {
|
|
if (combinedGlobalImports == null) {
|
|
ImportModel[] imports = globalImports.arrayCopy();
|
|
combinedGlobalImports = new CombinedImportModel(this, true, imports);
|
|
}
|
|
|
|
return combinedGlobalImports;
|
|
}
|
|
|
|
public BuiltinTypeModel addBuiltinType(String packageName, String typeName, BuiltinTypeBehaviour builtinTypeBehaviour) {
|
|
PackageModel p = getOrCreatePackage(packageName, true);
|
|
/*if (p.hasType(typeName)) {
|
|
throw new Error("Internal error/TODO: Type with same name as builtin '" + typeName + "' already exists in package '" + packageName + "'");
|
|
}*/
|
|
BuiltinTypeModel t = new BuiltinTypeModel(p, typeName, TypeLevel.OUTER, null, builtinTypeBehaviour);
|
|
p.addSyntheticType(t);
|
|
return t;
|
|
}
|
|
|
|
public AliasTypeModel addAliasType(String packageName, String typeName, String targetPackageName, String targetTypeName) {
|
|
PackageModel p = getOrCreatePackage(packageName, true);
|
|
AliasTypeModel t = new AliasTypeModel(p, typeName, TypeLevel.OUTER, null, getOrCreatePackage(targetPackageName, true), targetTypeName);
|
|
p.addSyntheticType(t);
|
|
return t;
|
|
}
|
|
|
|
public AliasTypeModel addInnerAliasType(UserTypeModel outer, String innerTypeName, String targetPackageName, String targetTypeName) {
|
|
PackageModel p = outer.getPackage();
|
|
AliasTypeModel t = new AliasTypeModel(p, innerTypeName, TypeLevel.INNER, outer, getOrCreatePackage(targetPackageName, true), targetTypeName);
|
|
p.addSyntheticType(t);
|
|
outer.registerInnerType(t);
|
|
return t;
|
|
}
|
|
|
|
public void addAliasPackage(String packageName, String targetPackageName) {
|
|
PackageModel tpkg = getOrCreatePackage(targetPackageName, true);
|
|
packageAliases.set(packageName, tpkg);
|
|
}
|
|
|
|
public void setTypeOptions(TypeOption[] typeOptions) {
|
|
this.typeOptions = typeOptions;
|
|
for (int i = 0; i < typeOptions.length; i++) {
|
|
TypeOption o = typeOptions[i];
|
|
if (o.isBuiltin) {
|
|
if (o.isNumber) {
|
|
addBuiltinType(CompilerWorld.pkgname(o.typeName), CompilerWorld.typname(o.typeName), new BuiltinTypeBehaviour.NumberBehaviour(o.isFloat, o.isSigned, o.nbits));
|
|
} else if (o.isDuck) {
|
|
addBuiltinType(CompilerWorld.pkgname(o.typeName), CompilerWorld.typname(o.typeName), new BuiltinTypeBehaviour.DuckBehaviour());
|
|
} else {
|
|
addBuiltinType(CompilerWorld.pkgname(o.typeName), CompilerWorld.typname(o.typeName), new BuiltinTypeBehaviour());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public TypeOption findTypeOption(TypeOption.Kind k) {
|
|
for (int i = 0; i < typeOptions.length; i++) {
|
|
if (typeOptions[i].kind == k) {
|
|
return typeOptions[i];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public boolean matchesTypeOption(TypeOption.Kind kind, TypeSignature type) {
|
|
TypeOption o = findTypeOption(kind);
|
|
if (o != null) {
|
|
if (o.getTypeSignature().mappableEquals(type)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*public void setDefaultBaseType(String packageName, String typeName) {
|
|
this.defaultBasePackage = packageName;
|
|
this.defaultBaseType = typeName;
|
|
}*/
|
|
|
|
public TypeModel getDefaultBaseType() {
|
|
TypeOption o = findTypeOption(TypeOption.Kind.OBJECT);
|
|
if (o != null) {
|
|
return getOrCreatePackage(CompilerWorld.pkgname(o.typeName), true).getType(CompilerWorld.typname(o.typeName));
|
|
}
|
|
return getOrCreatePackage(defaultBasePackage, true).getType(defaultBaseType);
|
|
}
|
|
|
|
public TypeModel getDefaultEnumBaseType() {
|
|
TypeOption o = findTypeOption(TypeOption.Kind.ENUMBASE);
|
|
if (o == null) {
|
|
return getDefaultBaseType(); // Fall back to "Object" or equivalent if there is no enum base type?
|
|
} else {
|
|
return getOrCreatePackage(CompilerWorld.pkgname(o.typeName), true).getType(CompilerWorld.typname(o.typeName));
|
|
}
|
|
}
|
|
|
|
public TypeModel getDefaultTypeType() {
|
|
TypeOption o = findTypeOption(TypeOption.Kind.TYPE);
|
|
if (o != null) {
|
|
return getOrCreatePackage(CompilerWorld.pkgname(o.typeName), true).getType(CompilerWorld.typname(o.typeName));
|
|
}
|
|
return getOrCreatePackage(defaultTypePackage, true).getType(defaultTypeType);
|
|
}
|
|
|
|
public TypeModel getDefaultStringType() {
|
|
TypeOption o = findTypeOption(TypeOption.Kind.STRING);
|
|
if (o != null) {
|
|
return getOrCreatePackage(CompilerWorld.pkgname(o.typeName), true).getType(CompilerWorld.typname(o.typeName));
|
|
}
|
|
return getOrCreatePackage(defaultStringPackage, true).getType(defaultStringType);
|
|
}
|
|
|
|
public TypeModel getDefaultBooleanType() {
|
|
TypeOption o = findTypeOption(TypeOption.Kind.BIT);
|
|
if (o != null) {
|
|
return getOrCreatePackage(CompilerWorld.pkgname(o.typeName), true).getType(CompilerWorld.typname(o.typeName));
|
|
}
|
|
return getOrCreatePackage(defaultBooleanPackage, true).getType(defaultBooleanType);
|
|
}
|
|
|
|
public TypeModel getDefaultInt32Type() {
|
|
TypeOption o = findTypeOption(TypeOption.Kind.INT32);
|
|
if (o != null) {
|
|
return getOrCreatePackage(CompilerWorld.pkgname(o.typeName), true).getType(CompilerWorld.typname(o.typeName));
|
|
}
|
|
return getOrCreatePackage(defaultInt32Package, true).getType(defaultInt32Type);
|
|
}
|
|
|
|
public TypeModel getDefaultInt64Type() {
|
|
TypeOption o = findTypeOption(TypeOption.Kind.INT64);
|
|
if (o != null) {
|
|
return getOrCreatePackage(CompilerWorld.pkgname(o.typeName), true).getType(CompilerWorld.typname(o.typeName));
|
|
}
|
|
return getOrCreatePackage(defaultInt64Package, true).getType(defaultInt64Type);
|
|
}
|
|
|
|
public TypeModel getDefaultUint32Type() {
|
|
TypeOption o = findTypeOption(TypeOption.Kind.UINT32);
|
|
if (o != null) {
|
|
return getOrCreatePackage(CompilerWorld.pkgname(o.typeName), true).getType(CompilerWorld.typname(o.typeName));
|
|
} else {
|
|
throw new Error("Uint64 type does not seem to have been enabled!");
|
|
}
|
|
}
|
|
|
|
public TypeModel getDefaultUint64Type() {
|
|
TypeOption o = findTypeOption(TypeOption.Kind.UINT64);
|
|
if (o != null) {
|
|
return getOrCreatePackage(CompilerWorld.pkgname(o.typeName), true).getType(CompilerWorld.typname(o.typeName));
|
|
} else {
|
|
throw new Error("Uint64 type does not seem to have been enabled!");
|
|
}
|
|
}
|
|
|
|
public TypeModel getDefaultFloat32Type() {
|
|
TypeOption o = findTypeOption(TypeOption.Kind.FLOAT32);
|
|
if (o != null) {
|
|
return getOrCreatePackage(CompilerWorld.pkgname(o.typeName), true).getType(CompilerWorld.typname(o.typeName));
|
|
}
|
|
return getOrCreatePackage(defaultFloat32Package, true).getType(defaultFloat32Type);
|
|
}
|
|
|
|
public TypeModel getDefaultFloat64Type() {
|
|
TypeOption o = findTypeOption(TypeOption.Kind.FLOAT64);
|
|
if (o != null) {
|
|
return getOrCreatePackage(CompilerWorld.pkgname(o.typeName), true).getType(CompilerWorld.typname(o.typeName));
|
|
}
|
|
return getOrCreatePackage(defaultFloat64Package, true).getType(defaultFloat64Type);
|
|
}
|
|
|
|
public TypeModel getDefaultDuckType() {
|
|
TypeOption o = findTypeOption(TypeOption.Kind.DUCK);
|
|
if (o != null) {
|
|
return getOrCreatePackage(CompilerWorld.pkgname(o.typeName), true).getType(CompilerWorld.typname(o.typeName));
|
|
}
|
|
return getOrCreatePackage(defaultDuckPackage, true).getType(defaultDuckType);
|
|
}
|
|
|
|
public TypeModel getDefaultVoidType() {
|
|
TypeOption o = findTypeOption(TypeOption.Kind.VOID);
|
|
if (o != null) {
|
|
return getOrCreatePackage(CompilerWorld.pkgname(o.typeName), true).getType(CompilerWorld.typname(o.typeName));
|
|
}
|
|
return getOrCreatePackage(defaultVoidPackage, true).getType(defaultVoidType);
|
|
}
|
|
|
|
public boolean hasPackage(String name) {
|
|
return packages.hasKey(name) || packageAliases.hasKey(name);
|
|
}
|
|
|
|
public PackageModel getOrCreatePackage(String name, boolean createIfNeeded) {
|
|
if (packages.hasKey(name)) {
|
|
return packages.get(name);
|
|
} else if (packageAliases.hasKey(name)) {
|
|
return packageAliases.get(name);
|
|
} else if (createIfNeeded) {
|
|
PackageModel p = new PackageModel(this, name);
|
|
packages.set(name, p);
|
|
return p;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public PackageModel getPackage(String name) {
|
|
if (hasPackage(name)) {
|
|
return packages.hasKey(name) ? packages.get(name) : packageAliases.get(name);
|
|
} else {
|
|
throw new Error("Internal error/TODO: Package '" + name + "' doesn't exist");
|
|
}
|
|
}
|
|
|
|
public String[] getPackageNames() {
|
|
List<String> list = new List<String>();
|
|
list.appendList(packages.keys());
|
|
list.sort(String.getDefaultComparisonOp());
|
|
return list.arrayCopy();
|
|
}
|
|
|
|
public int countErrors() {
|
|
int total = 0;
|
|
PackageModel[] pkgs = packages.values().arrayCopy();
|
|
for(int i = 0; i < pkgs.length; i++) {
|
|
PackageModel p = pkgs[i];
|
|
total += p.countErrors();
|
|
}
|
|
return total;
|
|
}
|
|
|
|
public int deleteErrors() {
|
|
int total = 0;
|
|
PackageModel[] pkgs = packages.values().arrayCopy();
|
|
for(int i = 0; i < pkgs.length; i++) {
|
|
PackageModel p = pkgs[i];
|
|
total += p.deleteErrors();
|
|
}
|
|
return total;
|
|
}
|
|
|
|
public int expand() {
|
|
int total = 0;
|
|
PackageModel[] pkgs = packages.values().arrayCopy();
|
|
for(int i = 0; i < pkgs.length; i++) {
|
|
PackageModel p = pkgs[i];
|
|
total += p.expand();
|
|
}
|
|
return total;
|
|
}
|
|
|
|
public int resolveTypes() {
|
|
int total = 0;
|
|
PackageModel[] pkgs = packages.values().arrayCopy();
|
|
for(int i = 0; i < pkgs.length; i++) {
|
|
PackageModel p = pkgs[i];
|
|
total += p.resolveTypes();
|
|
}
|
|
return total;
|
|
}
|
|
|
|
public int resolveExpressions(boolean includingReferences) {
|
|
int total = 0;
|
|
PackageModel[] pkgs = packages.values().arrayCopy();
|
|
for(int i = 0; i < pkgs.length; i++) {
|
|
PackageModel p = pkgs[i];
|
|
total += p.resolveExpressions(includingReferences);
|
|
}
|
|
return total;
|
|
}
|
|
|
|
public void dump(Reporter reporter) {
|
|
dump(reporter, "", " ");
|
|
}
|
|
|
|
public void dump(Reporter reporter, String indent, String incrindent) {
|
|
reporter.note("DUMP", indent + "> System");
|
|
String[] pkgs = getPackageNames();
|
|
for (int i = 0; i < pkgs.length; i++) {
|
|
getPackage(pkgs[i]).dump(reporter, indent + incrindent, incrindent);
|
|
}
|
|
}
|
|
|
|
public TypeModel getType(TypeSignature s) {
|
|
return getPackage(s.packageName).getType(s.typeName);
|
|
}
|
|
}
|