slcom/slangc/model/SystemModel.sauce

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);
}
}