Rename memory instructions; Rework constant handling

This commit is contained in:
dcodeIO
2018-07-18 23:49:32 +02:00
parent 34e8facfdc
commit a1b75b69b7
170 changed files with 26392 additions and 5185 deletions

View File

@ -132,6 +132,12 @@ class TypeAlias {
type: CommonTypeNode;
}
/** Represents a module-level export. */
class ModuleExport {
element: Element;
identifier: IdentifierExpression;
}
/** Represents the kind of an operator overload. */
export enum OperatorKind {
INVALID,
@ -319,7 +325,7 @@ export class Program extends DiagnosticEmitter {
/** File-level exports by exported name. */
fileLevelExports: Map<string,Element> = new Map();
/** Module-level exports by exported name. */
moduleLevelExports: Map<string,Element> = new Map();
moduleLevelExports: Map<string,ModuleExport> = new Map();
/** Array prototype reference. */
arrayPrototype: ClassPrototype | null = null;
@ -329,6 +335,10 @@ export class Program extends DiagnosticEmitter {
startFunction: FunctionPrototype;
/** Main function reference, if present. */
mainFunction: FunctionPrototype | null = null;
/** Abort function reference, if present. */
abortInstance: Function | null = null;
/** Memory allocation function. */
memoryAllocateInstance: Function | null = null;
/** Currently processing filespace. */
currentFilespace: Filespace;
@ -569,52 +579,54 @@ export class Program extends DiagnosticEmitter {
}
// set up global aliases
var globalAliases = options.globalAliases;
if (globalAliases) {
for (let [alias, name] of globalAliases) {
if (!name.length) continue; // explicitly disabled
let element = this.elementsLookup.get(name);
if (element) this.elementsLookup.set(alias, element);
else throw new Error("element not found: " + name);
{
let globalAliases = options.globalAliases;
if (globalAliases) {
for (let [alias, name] of globalAliases) {
if (!name.length) continue; // explicitly disabled
let element = this.elementsLookup.get(name);
if (element) this.elementsLookup.set(alias, element);
else throw new Error("element not found: " + name);
}
}
}
// register 'Array'
var arrayPrototype = this.elementsLookup.get("Array");
if (arrayPrototype) {
assert(arrayPrototype.kind == ElementKind.CLASS_PROTOTYPE);
this.arrayPrototype = <ClassPrototype>arrayPrototype;
if (this.elementsLookup.has("Array")) {
let element = assert(this.elementsLookup.get("Array"));
assert(element.kind == ElementKind.CLASS_PROTOTYPE);
this.arrayPrototype = <ClassPrototype>element;
}
// register 'String'
var stringPrototype = this.elementsLookup.get("String");
if (stringPrototype) {
assert(stringPrototype.kind == ElementKind.CLASS_PROTOTYPE);
let stringInstance = resolver.resolveClass(<ClassPrototype>stringPrototype, null);
if (stringInstance) {
if (this.elementsLookup.has("String")) {
let element = assert(this.elementsLookup.get("String"));
assert(element.kind == ElementKind.CLASS_PROTOTYPE);
let instance = resolver.resolveClass(<ClassPrototype>element, null);
if (instance) {
if (this.typesLookup.has("string")) {
let declaration = (<ClassPrototype>stringPrototype).declaration;
let declaration = (<ClassPrototype>element).declaration;
this.error(
DiagnosticCode.Duplicate_identifier_0,
declaration.name.range, declaration.programLevelInternalName
);
} else {
this.stringInstance = stringInstance;
this.typesLookup.set("string", stringInstance.type);
this.stringInstance = instance;
this.typesLookup.set("string", instance.type);
}
}
}
// register 'start'
{
let element = <Element>assert(this.elementsLookup.get("start"));
let element = assert(this.elementsLookup.get("start"));
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
this.startFunction = <FunctionPrototype>element;
}
// register 'main' if present
if (this.moduleLevelExports.has("main")) {
let element = <Element>this.moduleLevelExports.get("main");
if (this.elementsLookup.has("main")) {
let element = <Element>this.elementsLookup.get("main");
if (
element.kind == ElementKind.FUNCTION_PROTOTYPE &&
!(<FunctionPrototype>element).isAny(CommonFlags.GENERIC | CommonFlags.AMBIENT)
@ -623,6 +635,28 @@ export class Program extends DiagnosticEmitter {
this.mainFunction = <FunctionPrototype>element;
}
}
// register 'abort' if present
if (this.elementsLookup.has("abort")) {
let element = <Element>this.elementsLookup.get("abort");
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
let instance = this.resolver.resolveFunction(<FunctionPrototype>element, null);
if (instance) this.abortInstance = instance;
}
// register 'memory.allocate' if present
if (this.elementsLookup.has("memory")) {
let element = <Element>this.elementsLookup.get("memory");
let members = element.members;
if (members) {
if (members.has("allocate")) {
element = assert(members.get("allocate"));
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
let instance = this.resolver.resolveFunction(<FunctionPrototype>element, null);
if (instance) this.memoryAllocateInstance = instance;
}
}
}
}
/** Sets a constant integer value. */
@ -824,14 +858,18 @@ export class Program extends DiagnosticEmitter {
this.currentFilespace.members.set(simpleName, prototype);
if (prototype.is(CommonFlags.EXPORT) && declaration.range.source.isEntry) {
if (this.moduleLevelExports.has(simpleName)) {
let existingExport = <ModuleExport>this.moduleLevelExports.get(simpleName);
this.error(
DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0,
declaration.name.range, (<Element>this.moduleLevelExports.get(simpleName)).internalName
declaration.name.range, existingExport.element.internalName
);
return;
}
prototype.set(CommonFlags.MODULE_EXPORT);
this.moduleLevelExports.set(simpleName, prototype);
this.moduleLevelExports.set(simpleName, <ModuleExport>{
element: prototype,
identifier: declaration.name
});
}
}
@ -1269,14 +1307,18 @@ export class Program extends DiagnosticEmitter {
this.currentFilespace.members.set(simpleName, element);
if (declaration.range.source.isEntry) {
if (this.moduleLevelExports.has(simpleName)) {
let existingExport = <ModuleExport>this.moduleLevelExports.get(simpleName);
this.error(
DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0,
declaration.name.range, (<Element>this.moduleLevelExports.get(simpleName)).internalName
declaration.name.range, existingExport.element.internalName
);
return;
}
element.set(CommonFlags.MODULE_EXPORT);
this.moduleLevelExports.set(simpleName, element);
this.moduleLevelExports.set(simpleName, <ModuleExport>{
element,
identifier: declaration.name
});
}
}
@ -1332,31 +1374,39 @@ export class Program extends DiagnosticEmitter {
private setExportAndCheckLibrary(
internalName: string,
element: Element,
identifier: IdentifierExpression
externalIdentifier: IdentifierExpression
): void {
// add to file-level exports
this.fileLevelExports.set(internalName, element);
// add to filespace
var internalPath = identifier.range.source.internalPath;
var internalPath = externalIdentifier.range.source.internalPath;
var prefix = FILESPACE_PREFIX + internalPath;
var filespace = this.elementsLookup.get(prefix);
if (!filespace) filespace = assert(this.elementsLookup.get(prefix + PATH_DELIMITER + "index"));
assert(filespace.kind == ElementKind.FILESPACE);
var simpleName = identifier.text;
var simpleName = externalIdentifier.text;
(<Filespace>filespace).members.set(simpleName, element);
// add global alias if from a library file
if (identifier.range.source.isLibrary) {
// add global alias if a top-level export of a library file
var source = externalIdentifier.range.source;
if (source.isLibrary) {
if (this.elementsLookup.has(simpleName)) {
this.error(
DiagnosticCode.Export_declaration_conflicts_with_exported_declaration_of_0,
identifier.range, simpleName
externalIdentifier.range, simpleName
);
} else {
element.internalName = simpleName;
this.elementsLookup.set(simpleName, element);
}
// add module level export if a top-level export of an entry file
} else if (source.isEntry) {
this.moduleLevelExports.set(externalIdentifier.text, <ModuleExport>{
element,
identifier: externalIdentifier
});
}
}
@ -1382,10 +1432,10 @@ export class Program extends DiagnosticEmitter {
referencedName = member.range.source.internalPath + PATH_DELIMITER + member.name.text;
// resolve right away if the element exists
if (referencedElement = this.elementsLookup.get(referencedName)) {
if (this.elementsLookup.has(referencedName)) {
this.setExportAndCheckLibrary(
externalName,
referencedElement,
<Element>this.elementsLookup.get(referencedName),
member.externalName
);
return;
@ -1526,14 +1576,18 @@ export class Program extends DiagnosticEmitter {
this.currentFilespace.members.set(simpleName, prototype);
if (declaration.range.source.isEntry) {
if (this.moduleLevelExports.has(simpleName)) {
let existingExport = <ModuleExport>this.moduleLevelExports.get(simpleName);
this.error(
DiagnosticCode.Duplicate_identifier_0,
declaration.name.range, (<Element>this.moduleLevelExports.get(simpleName)).internalName
declaration.name.range, existingExport.element.internalName
);
return;
}
prototype.set(CommonFlags.MODULE_EXPORT);
this.moduleLevelExports.set(simpleName, prototype);
this.moduleLevelExports.set(simpleName, <ModuleExport>{
element: prototype,
identifier: declaration.name
});
}
}
@ -1687,14 +1741,18 @@ export class Program extends DiagnosticEmitter {
this.currentFilespace.members.set(simpleName, prototype);
if (declaration.range.source.isEntry) {
if (this.moduleLevelExports.has(simpleName)) {
let existingExport = <ModuleExport>this.moduleLevelExports.get(simpleName);
this.error(
DiagnosticCode.Duplicate_identifier_0,
declaration.name.range, (<Element>this.moduleLevelExports.get(simpleName)).internalName
declaration.name.range, existingExport.element.internalName
);
return;
}
prototype.set(CommonFlags.MODULE_EXPORT);
this.moduleLevelExports.set(simpleName, prototype);
this.moduleLevelExports.set(simpleName, <ModuleExport>{
element: prototype,
identifier: declaration.name
});
}
}
@ -1772,15 +1830,19 @@ export class Program extends DiagnosticEmitter {
this.currentFilespace.members.set(simpleName, namespace);
if (declaration.range.source.isEntry) {
if (this.moduleLevelExports.has(simpleName)) {
if (this.moduleLevelExports.get(simpleName) !== namespace) { // not merged
let existingExport = <ModuleExport>this.moduleLevelExports.get(simpleName);
if (existingExport.element !== namespace) { // not merged
this.error(
DiagnosticCode.Duplicate_identifier_0,
declaration.name.range, (<Element>this.moduleLevelExports.get(simpleName)).internalName
declaration.name.range, existingExport.element.internalName
);
return;
}
} else {
this.moduleLevelExports.set(simpleName, namespace);
this.moduleLevelExports.set(simpleName, <ModuleExport>{
element: namespace,
identifier: declaration.name
});
}
namespace.set(CommonFlags.MODULE_EXPORT);
}
@ -1869,6 +1931,7 @@ export class Program extends DiagnosticEmitter {
decorators
? this.checkDecorators(decorators,
DecoratorFlags.GLOBAL |
DecoratorFlags.INLINE |
DecoratorFlags.EXTERNAL
)
: DecoratorFlags.NONE
@ -1904,14 +1967,18 @@ export class Program extends DiagnosticEmitter {
this.currentFilespace.members.set(simpleName, global);
if (declaration.range.source.isEntry) {
if (this.moduleLevelExports.has(simpleName)) {
let existingExport = <ModuleExport>this.moduleLevelExports.get(simpleName);
this.error(
DiagnosticCode.Duplicate_identifier_0,
declaration.name.range, (<Element>this.moduleLevelExports.get(simpleName)).internalName
declaration.name.range, existingExport.element.internalName
);
continue;
}
global.set(CommonFlags.MODULE_EXPORT);
this.moduleLevelExports.set(simpleName, global);
this.moduleLevelExports.set(simpleName, <ModuleExport>{
element: global,
identifier: declaration.name
});
}
}
this.checkGlobal(global, declaration);