More options for asc

This commit is contained in:
dcodeIO
2017-12-04 19:26:50 +01:00
parent 0e6bfa45f8
commit df3e34f2aa
17 changed files with 565 additions and 32 deletions

View File

@ -412,7 +412,9 @@ export class Compiler extends DiagnosticEmitter {
if (!element || element.kind != ElementKind.FUNCTION_PROTOTYPE)
throw new Error("unexpected missing function");
const instance: Function | null = this.compileFunctionUsingTypeArguments(<FunctionPrototype>element, typeArguments, contextualTypeArguments, alternativeReportNode);
if (instance && declaration.range.source.isEntry && declaration.parent == declaration.range.source && hasModifier(ModifierKind.EXPORT, declaration.modifiers))
if (!instance)
return;
if (declaration.range.source.isEntry && declaration.parent == declaration.range.source && hasModifier(ModifierKind.EXPORT, declaration.modifiers))
this.module.addExport(instance.internalName, declaration.identifier.name);
}
@ -431,19 +433,29 @@ export class Compiler extends DiagnosticEmitter {
if (!declaration)
throw new Error("unexpected missing declaration");
if (!declaration.statements) {
this.error(DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration, declaration.identifier.range);
return false;
if (instance.isDeclare) {
if (declaration.statements) {
this.error(DiagnosticCode.An_implementation_cannot_be_declared_in_ambient_contexts, declaration.identifier.range);
return false;
}
} else {
if (!declaration.statements) {
this.error(DiagnosticCode.Function_implementation_is_missing_or_not_immediately_following_the_declaration, declaration.identifier.range);
return false;
}
}
instance.isCompiled = true;
// compile statements
const previousFunction: Function = this.currentFunction;
this.currentFunction = instance;
const stmts: ExpressionRef[] = this.compileStatements(<Statement[]>declaration.statements);
this.currentFunction = previousFunction;
let stmts: ExpressionRef[] | null = null;
if (!instance.isDeclare) {
const previousFunction: Function = this.currentFunction;
this.currentFunction = instance;
stmts = this.compileStatements(<Statement[]>declaration.statements);
this.currentFunction = previousFunction;
}
// create the function
// create the function type
let k: i32 = instance.parameters.length;
const binaryenResultType: NativeType = typeToNativeType(instance.returnType);
const binaryenParamTypes: NativeType[] = new Array(k);
@ -456,8 +468,14 @@ export class Compiler extends DiagnosticEmitter {
let typeRef: FunctionTypeRef = this.module.getFunctionTypeBySignature(binaryenResultType, binaryenParamTypes);
if (!typeRef)
typeRef = this.module.addFunctionType(signatureNameParts.join(""), binaryenResultType, binaryenParamTypes);
// create the function
const internalName: string = instance.internalName;
this.module.addFunction(internalName, typeRef, typesToNativeTypes(instance.additionalLocals), this.module.createBlock(null, stmts, NativeType.None));
if (instance.isDeclare) {
this.module.addImport(internalName, "env", declaration.identifier.name, typeRef);
} else {
this.module.addFunction(internalName, typeRef, typesToNativeTypes(instance.additionalLocals), this.module.createBlock(null, <ExpressionRef[]>stmts, NativeType.None));
}
return true;
}
@ -1732,7 +1750,7 @@ export class Compiler extends DiagnosticEmitter {
this.compileFunction(functionInstance);
// imported function
if (functionInstance.isImport)
if (functionInstance.isDeclare)
return this.module.createCallImport(functionInstance.internalName, operands, typeToNativeType(functionInstance.returnType));
// internal function

View File

@ -12,3 +12,23 @@ const binaryen = require("binaryen");
for (const key in binaryen)
if (/^_(?:Binaryen|Relooper|malloc$|free$)/.test(key))
globalScope[key] = binaryen[key];
import { Module } from "../module";
Module.prototype.toBinary = function(bufferSize = 1048576): Uint8Array {
const ptr = _malloc(bufferSize);
const len = this.write(ptr, bufferSize);
const ret = new Uint8Array(len);
ret.set(binaryen.HEAPU8.subarray(ptr, ptr + len));
_free(ptr);
return ret;
}
Module.prototype.toText = function(): string {
let previousPrint: any = (<any>binaryen)["print"];
let ret: string = "";
binaryen["print"] = function(x: string): void { ret += x + "\n" };
this.print();
binaryen["print"] = previousPrint;
return ret;
}

View File

@ -617,11 +617,21 @@ export class Module {
return _BinaryenModuleInterpret(this.ref);
}
toBinary(): Uint8Array {
write(output: usize, outputSize: usize = 1048576): usize {
return _BinaryenModuleWrite(this.ref, output, outputSize);
}
print(): void {
return _BinaryenModulePrint(this.ref);
}
toBinary(bufferSize: usize = 1048576): Uint8Array {
// FIXME: target specific / JS glue overrides this
throw new Error("not implemented");
}
toText(): string {
// FIXME: target specific / JS glue overrides this
throw new Error("not implemented");
}

View File

@ -380,6 +380,9 @@ export class Program extends DiagnosticEmitter {
else
this.exports.set(internalName, prototype);
}
if (hasModifier(ModifierKind.DECLARE, declaration.modifiers)) {
prototype.isDeclare = true;
}
}
private initializeImports(statement: ImportStatement, queuedExports: Map<string,QueuedExport>, queuedImports: QueuedImport[]): void {
@ -689,6 +692,7 @@ export abstract class Element {
isCompiled: bool = false;
isImport: bool = false;
isBuiltin: bool = false;
isDeclare: bool = false;
constructor(program: Program, internalName: string) {
this.program = program;
@ -922,6 +926,7 @@ export class Function extends Element {
this.returnType = returnType;
this.instanceMethodOf = instanceMethodOf;
this.isBuiltin = prototype.isBuiltin;
this.isDeclare = prototype.isDeclare;
let localIndex: i32 = 0;
if (instanceMethodOf) {
this.locals.set("this", new Local(prototype.program, "this", localIndex++, instanceMethodOf.type));