Comparing version 0.1.11 to 0.1.12-20200206214526.commit-173e6f1
import { Local, Nodes, Global } from './nodes'; | ||
import { FunctionSignatureType } from './types'; | ||
export declare abstract class Annotation { | ||
@@ -47,2 +48,7 @@ get name(): string; | ||
} | ||
class FunctionInTable extends Annotation { | ||
nameIdentifier: Nodes.NameIdentifierNode; | ||
constructor(nameIdentifier: Nodes.NameIdentifierNode); | ||
toString(): string; | ||
} | ||
class LocalIdentifier extends Annotation { | ||
@@ -64,2 +70,6 @@ local: Local | Global; | ||
} | ||
class IsFunctionReference extends Annotation { | ||
fun: FunctionSignatureType; | ||
constructor(fun: FunctionSignatureType); | ||
} | ||
class IsUnreachable extends Annotation { | ||
@@ -66,0 +76,0 @@ } |
@@ -73,2 +73,12 @@ "use strict"; | ||
annotations.LabelId = LabelId; | ||
class FunctionInTable extends Annotation { | ||
constructor(nameIdentifier) { | ||
super(); | ||
this.nameIdentifier = nameIdentifier; | ||
} | ||
toString() { | ||
return `FunctionInTable(${this.nameIdentifier.name})`; | ||
} | ||
} | ||
annotations.FunctionInTable = FunctionInTable; | ||
class LocalIdentifier extends Annotation { | ||
@@ -111,2 +121,9 @@ constructor(local) { | ||
annotations.ImplicitCall = ImplicitCall; | ||
class IsFunctionReference extends Annotation { | ||
constructor(fun) { | ||
super(); | ||
this.fun = fun; | ||
} | ||
} | ||
annotations.IsFunctionReference = IsFunctionReference; | ||
class IsUnreachable extends Annotation { | ||
@@ -113,0 +130,0 @@ } |
@@ -118,3 +118,3 @@ "use strict"; | ||
constructor(type, node) { | ||
super(`Type mismatch: Type ${printDebugType(type)}" is not a function`, node); | ||
super(`Type mismatch: Type ${printDebugType(type)} is not a function`, node); | ||
this.type = type; | ||
@@ -121,0 +121,0 @@ } |
@@ -94,5 +94,5 @@ import { TokenError } from 'ebnf'; | ||
} | ||
class FunctionParameterTypeNode extends TypeNode { | ||
class SignatureParameterNode extends TypeNode { | ||
readonly parameterType: TypeNode; | ||
name?: NameIdentifierNode; | ||
parameterName?: NameIdentifierNode; | ||
constructor(astNode: ASTNode, parameterType: TypeNode); | ||
@@ -102,7 +102,7 @@ get childrenOrEmpty(): (NameIdentifierNode | TypeNode | undefined)[]; | ||
class FunctionTypeNode extends TypeNode { | ||
readonly parameters: FunctionParameterTypeNode[]; | ||
readonly parameters: SignatureParameterNode[]; | ||
typeParameters?: string[]; | ||
effect?: TypeNode; | ||
returnType?: TypeNode; | ||
constructor(astNode: ASTNode, parameters: FunctionParameterTypeNode[]); | ||
constructor(astNode: ASTNode, parameters: SignatureParameterNode[]); | ||
get childrenOrEmpty(): (TypeNode | undefined)[]; | ||
@@ -113,3 +113,3 @@ } | ||
typeParameters?: string[]; | ||
parameters?: FunctionParameterTypeNode[]; | ||
parameters?: SignatureParameterNode[]; | ||
returnType?: TypeNode; | ||
@@ -116,0 +116,0 @@ get childrenOrEmpty(): (NameIdentifierNode | undefined)[]; |
@@ -171,3 +171,3 @@ "use strict"; | ||
Nodes.TypeReducerNode = TypeReducerNode; | ||
class FunctionParameterTypeNode extends TypeNode { | ||
class SignatureParameterNode extends TypeNode { | ||
constructor(astNode, parameterType) { | ||
@@ -178,6 +178,6 @@ super(astNode); | ||
get childrenOrEmpty() { | ||
return [this.name, this.parameterType]; | ||
return [this.parameterName, this.parameterType]; | ||
} | ||
} | ||
Nodes.FunctionParameterTypeNode = FunctionParameterTypeNode; | ||
Nodes.SignatureParameterNode = SignatureParameterNode; | ||
class FunctionTypeNode extends TypeNode { | ||
@@ -184,0 +184,0 @@ constructor(astNode, parameters) { |
@@ -9,5 +9,10 @@ import { MessageCollector } from './MessageCollector'; | ||
modulesInContext: Map<string, Nodes.DocumentNode>; | ||
functionsInTable: Set<string>; | ||
signatures: Map<string, any>; | ||
private typeNumbers; | ||
constructor(system: System); | ||
reset(): void; | ||
addFunctionToTable(funInternalIdentifier: string): void; | ||
getOrderedTable(): string[]; | ||
getFunctionInTableNumber(funInternalIdentifier: string): number; | ||
/** | ||
@@ -14,0 +19,0 @@ * Invalidates a module and it's dependencies. This function should be called |
@@ -12,2 +12,5 @@ "use strict"; | ||
this.modulesInContext = new Map(); | ||
// internalIdentifiers of the functions that should be part of the wasm table | ||
this.functionsInTable = new Set(); | ||
this.signatures = new Map(); | ||
this.typeNumbers = new Map(); | ||
@@ -18,4 +21,17 @@ // stub | ||
this.typeNumbers.clear(); | ||
this.functionsInTable.clear(); | ||
this.signatures.clear(); | ||
this.messageCollector.errors.length = 0; | ||
} | ||
addFunctionToTable(funInternalIdentifier) { | ||
this.functionsInTable.add(funInternalIdentifier); | ||
} | ||
getOrderedTable() { | ||
return Array.from(this.functionsInTable); | ||
} | ||
getFunctionInTableNumber(funInternalIdentifier) { | ||
// change my mind | ||
this.addFunctionToTable(funInternalIdentifier); | ||
return this.getOrderedTable().indexOf(funInternalIdentifier); | ||
} | ||
/** | ||
@@ -30,2 +46,7 @@ * Invalidates a module and it's dependencies. This function should be called | ||
this.modulesInContext.delete(moduleName); | ||
this.functionsInTable.forEach($ => { | ||
if ($.startsWith(moduleName + '::')) { | ||
this.functionsInTable.delete($); | ||
} | ||
}); | ||
currentModule.importedBy.forEach(importedBy => { | ||
@@ -32,0 +53,0 @@ this.invalidateModule(importedBy); |
@@ -328,4 +328,4 @@ "use strict"; | ||
const type = visitChildTypeOrFail(astNode, 'Type'); | ||
const ret = new nodes_1.Nodes.FunctionParameterTypeNode(astNode, type); | ||
ret.name = visitChildTypeOrNull(astNode, 'NameIdentifier'); | ||
const ret = new nodes_1.Nodes.SignatureParameterNode(astNode, type); | ||
ret.parameterName = visitChildTypeOrNull(astNode, 'NameIdentifier'); | ||
return ret; | ||
@@ -332,0 +332,0 @@ }, |
@@ -41,17 +41,29 @@ "use strict"; | ||
} | ||
function getTypeForFunction(fn) { | ||
const fnType = types_1.TypeHelpers.getNodeType(fn.functionName); | ||
if (fnType && fnType instanceof types_1.FunctionType) { | ||
if (fnType.returnType) { | ||
const ret = fnType.returnType; | ||
function getTypeForFunctionType(fn, errorNode) { | ||
if (!fn) { | ||
throw new NodeError_1.LysCompilerError('node has no type', errorNode); | ||
} | ||
else if (fn instanceof types_1.FunctionSignatureType) { | ||
if (fn.returnType) { | ||
const ret = fn.returnType; | ||
const retType = ret.binaryenType ? [ret.binaryenType] : []; | ||
return t.signature(fn.parameters.map(($, $$) => ({ | ||
id: $.parameterName.name, | ||
valtype: fnType.parameterTypes[$$].binaryenType | ||
// tslint:disable:ter-indent | ||
return t.signature(fn.parameterTypes.map(($, $$) => ({ | ||
id: fn.parameterNames[$$] || '$param' + $$, | ||
valtype: $.binaryenType | ||
})), retType); | ||
} | ||
throw new NodeError_1.LysCompilerError(fnType + ' has no return type', fn); | ||
throw new NodeError_1.LysCompilerError(fn + ' has no return type', errorNode); | ||
} | ||
else { | ||
throw new NodeError_1.LysCompilerError(fn + ' is not a function 1', errorNode); | ||
} | ||
} | ||
function getTypeForFunction(fn) { | ||
const fnType = types_1.TypeHelpers.getNodeType(fn.functionName); | ||
if (fnType && fnType instanceof types_1.FunctionType) { | ||
return getTypeForFunctionType(fnType.signature, fn); | ||
} | ||
else if (fnType) { | ||
throw new NodeError_1.LysCompilerError(fnType + ' is not a function', fn); | ||
throw new NodeError_1.LysCompilerError(fnType + ' is not a function 2', fn); | ||
} | ||
@@ -62,3 +74,3 @@ else { | ||
} | ||
function emitFunction(fn, document) { | ||
function emitFunction(fn, document, parsingContext) { | ||
const fnType = getTypeForFunction(fn); | ||
@@ -71,7 +83,7 @@ restartFunctionSeqId(fn); | ||
fnType, // signature | ||
[...locals, ...emitList(fn.body, document)] // body | ||
[...locals, ...emitList(fn.body, document, parsingContext)] // body | ||
); | ||
return moduleFun; | ||
} | ||
function emitLoop(node, document) { | ||
function emitLoop(node, document, parsingContext) { | ||
const loopId = getFunctionSeqId(node); | ||
@@ -81,9 +93,11 @@ node.annotate(new annotations_1.annotations.LabelId(loopId)); | ||
const breakLabel = t.identifier('Break' + loopId); | ||
return t.blockInstruction(breakLabel, [t.loopInstruction(continueLabel, void 0, emitList(node.body, document))]); | ||
return t.blockInstruction(breakLabel, [ | ||
t.loopInstruction(continueLabel, void 0, emitList(node.body, document, parsingContext)) | ||
]); | ||
} | ||
function emitMatchingNode(match, document) { | ||
function emitMatchingNode(match, document, parsingContext) { | ||
const matchers = match.matchingSet.slice(0); | ||
const ixDefaultBranch = matchers.findIndex($ => $ instanceof nodes_1.Nodes.MatchDefaultNode); | ||
const local = match.getAnnotation(annotations_1.annotations.LocalIdentifier).local; | ||
const lhs = t.instruction('local.set', [t.identifier(local.name), emit(match.lhs, document)]); | ||
const lhs = t.instruction('local.set', [t.identifier(local.name), emit(match.lhs, document, parsingContext)]); | ||
if (ixDefaultBranch !== -1) { | ||
@@ -98,3 +112,3 @@ // the default branch must be the last element | ||
if (node instanceof nodes_1.Nodes.MatchDefaultNode) { | ||
const body = emit(node.rhs, document); | ||
const body = emit(node.rhs, document, parsingContext); | ||
return { condition: null, body }; | ||
@@ -109,5 +123,5 @@ } | ||
t.instruction('local.get', [t.identifier(local.name)]), | ||
emit(node.literal, document) | ||
emit(node.literal, document, parsingContext) | ||
]); | ||
const body = emit(node.rhs, document); | ||
const body = emit(node.rhs, document, parsingContext); | ||
return { | ||
@@ -126,3 +140,3 @@ condition, | ||
]); | ||
const body = emit(node.rhs, document); | ||
const body = emit(node.rhs, document, parsingContext); | ||
return { | ||
@@ -153,11 +167,11 @@ condition, | ||
} | ||
function emitList(nodes, document) { | ||
function emitList(nodes, document, parsingContext) { | ||
if (nodes instanceof Array) { | ||
return helpers_1.flatten(nodes.map($ => emit($, document))); | ||
return helpers_1.flatten(nodes.map($ => emit($, document, parsingContext))); | ||
} | ||
else { | ||
return helpers_1.flatten([emit(nodes, document)]); | ||
return helpers_1.flatten([emit(nodes, document, parsingContext)]); | ||
} | ||
} | ||
function emitWast(node, document) { | ||
function emitWast(node, document, parsingContext) { | ||
if (node instanceof nodes_1.Nodes.ReferenceNode) { | ||
@@ -190,5 +204,5 @@ let ofType = types_1.TypeHelpers.getNodeType(node); | ||
} | ||
return t.instruction(node.symbol, (node.args || []).map($ => emitWast($, document))); | ||
return t.instruction(node.symbol, (node.args || []).map($ => emitWast($, document, parsingContext))); | ||
} | ||
function emitImplicitCall(node, document) { | ||
function emitImplicitCall(node, document, parsingContext) { | ||
const implicitCallData = node.getAnnotation(annotations_1.annotations.ImplicitCall); | ||
@@ -200,8 +214,50 @@ const ofType = implicitCallData.implicitCall.resolvedFunctionType; | ||
throw new NodeError_1.LysCompilerError('implicit call is not a function', node); | ||
return t.callInstruction(t.identifier(ofType.name.internalIdentifier), implicitCallData.implicitCall.argumentsNode.map($ => emit($, document))); | ||
return t.callInstruction(t.identifier(ofType.name.internalIdentifier), implicitCallData.implicitCall.argumentsNode.map($ => emit($, document, parsingContext))); | ||
} | ||
function emit(node, document) { | ||
function getReferencedSymbol(node) { | ||
const local = node.getAnnotation(annotations_1.annotations.LocalIdentifier); | ||
if (local) { | ||
return { | ||
symbol: local.local.name, | ||
type: 'VALUE' | ||
}; | ||
} | ||
const fn = node.getAnnotation(annotations_1.annotations.FunctionInTable); | ||
if (fn) { | ||
if (!fn.nameIdentifier.internalIdentifier) { | ||
throw new NodeError_1.LysCompilerError('fn.nameIdentifier.internalIdentifier is falsy', node); | ||
} | ||
return { | ||
symbol: fn.nameIdentifier.internalIdentifier, | ||
type: 'TABLE' | ||
}; | ||
} | ||
throw new NodeError_1.LysCompilerError('Cannot resolve WASM symbol', node); | ||
} | ||
function getTypeSignature(fn, errorNode, parsingContext) { | ||
if (!fn) { | ||
throw new NodeError_1.LysCompilerError('node has no type', errorNode); | ||
} | ||
else if (fn instanceof types_1.FunctionSignatureType) { | ||
if (fn.returnType) { | ||
const ret = fn.returnType; | ||
const retType = ret.binaryenType ? [ret.binaryenType] : []; | ||
const name = 'lys::' + fn.parameterTypes.map($ => $.binaryenType).join('_') + '->' + (retType.join('_') || 'void'); | ||
if (!parsingContext.signatures.has(name)) { | ||
parsingContext.signatures.set(name, t.typeInstruction(t.identifier(name), t.signature(fn.parameterTypes.map($ => ({ | ||
valtype: $.binaryenType | ||
})), retType))); | ||
} | ||
return t.identifier(name); | ||
} | ||
throw new NodeError_1.LysCompilerError(fn + ' has no return type', errorNode); | ||
} | ||
else { | ||
throw new NodeError_1.LysCompilerError(fn + ' is not a function 1', errorNode); | ||
} | ||
} | ||
function emit(node, document, parsingContext) { | ||
function _emit() { | ||
if (node.hasAnnotation(annotations_1.annotations.ImplicitCall)) { | ||
return emitImplicitCall(node, document); | ||
return emitImplicitCall(node, document, parsingContext); | ||
} | ||
@@ -211,4 +267,14 @@ else if (node instanceof nodes_1.Nodes.AbstractFunctionCallNode) { | ||
if (!funType && node.hasAnnotation(annotations_1.annotations.ByPassFunction)) { | ||
return emit(node.argumentsNode[0], document); | ||
return emit(node.argumentsNode[0], document, parsingContext); | ||
} | ||
if (!funType && node instanceof nodes_1.Nodes.FunctionCallNode) { | ||
const annotation = node.getAnnotation(annotations_1.annotations.IsFunctionReference); | ||
if (annotation) { | ||
const fnType = types_1.TypeHelpers.getNodeType(node.functionNode); | ||
const signature = getTypeSignature(fnType, node, parsingContext); | ||
return t.callIndirectInstruction(signature, node.argumentsNode | ||
.map($ => emit($, document, parsingContext)) | ||
.concat(emit(node.functionNode, document, parsingContext))); | ||
} | ||
} | ||
if (!funType) { | ||
@@ -219,3 +285,3 @@ throw new NodeError_1.LysCompilerError(`funType is falsy`, node); | ||
throw new NodeError_1.LysCompilerError(`${funType}.internalIdentifier is falsy`, node); | ||
return t.callInstruction(t.identifier(funType.name.internalIdentifier), node.argumentsNode.map($ => emit($, document))); | ||
return t.callInstruction(t.identifier(funType.name.internalIdentifier), node.argumentsNode.map($ => emit($, document, parsingContext))); | ||
} | ||
@@ -226,3 +292,3 @@ else if (node instanceof nodes_1.Nodes.UnknownExpressionNode) { | ||
else if (node instanceof nodes_1.Nodes.WasmExpressionNode) { | ||
return helpers_1.flatten(node.atoms.map($ => emitWast($, document))); | ||
return helpers_1.flatten(node.atoms.map($ => emitWast($, document, parsingContext))); | ||
} | ||
@@ -254,10 +320,10 @@ else if (node instanceof nodes_1.Nodes.ContinueNode) { | ||
else if (node instanceof nodes_1.Nodes.PatternMatcherNode) { | ||
return emitMatchingNode(node, document); | ||
return emitMatchingNode(node, document, parsingContext); | ||
} | ||
else if (node instanceof nodes_1.Nodes.LoopNode) { | ||
return emitLoop(node, document); | ||
return emitLoop(node, document, parsingContext); | ||
} | ||
else if (node instanceof nodes_1.Nodes.VarDeclarationNode) { | ||
const local = node.getAnnotation(annotations_1.annotations.LocalIdentifier).local; | ||
return t.instruction('local.set', [t.identifier(local.name), emit(node.value, document)]); | ||
return t.instruction('local.set', [t.identifier(local.name), emit(node.value, document, parsingContext)]); | ||
} | ||
@@ -271,3 +337,3 @@ else if (node instanceof nodes_1.Nodes.AssignmentNode) { | ||
const local = node.lhs.getAnnotation(annotations_1.annotations.LocalIdentifier).local; | ||
return t.instruction(instr, [t.identifier(local.name), emit(node.rhs, document)]); | ||
return t.instruction(instr, [t.identifier(local.name), emit(node.rhs, document, parsingContext)]); | ||
} | ||
@@ -278,3 +344,3 @@ else { | ||
return t.blockInstruction(t.identifier('tee_global_' + getFunctionSeqId(node)), [ | ||
t.instruction('global.set', [t.identifier(local.name), emit(node.rhs, document)]), | ||
t.instruction('global.set', [t.identifier(local.name), emit(node.rhs, document, parsingContext)]), | ||
t.instruction('global.get', [t.identifier(local.name)]) | ||
@@ -285,3 +351,3 @@ ], types_1.TypeHelpers.getNodeType(node.rhs).binaryenType); | ||
const local = node.lhs.getAnnotation(annotations_1.annotations.LocalIdentifier).local; | ||
return t.instruction('global.set', [t.identifier(local.name), emit(node.rhs, document)]); | ||
return t.instruction('global.set', [t.identifier(local.name), emit(node.rhs, document, parsingContext)]); | ||
} | ||
@@ -301,3 +367,3 @@ } | ||
// TODO: Drop here things | ||
let emited = emit($, document); | ||
let emited = emit($, document, parsingContext); | ||
const type = types_1.TypeHelpers.getNodeType($); | ||
@@ -320,8 +386,15 @@ if (type && type.binaryenType !== undefined && !$.hasAnnotation(annotations_1.annotations.IsValueNode)) { | ||
else if (node instanceof nodes_1.Nodes.IfNode) { | ||
return t.ifInstruction(t.identifier('IF' + getFunctionSeqId(node)), [emit(node.condition, document)], types_1.TypeHelpers.getNodeType(node).binaryenType, emitList(node.truePart, document), node.falsePart ? emitList(node.falsePart, document) : []); | ||
return t.ifInstruction(t.identifier('IF' + getFunctionSeqId(node)), [emit(node.condition, document, parsingContext)], types_1.TypeHelpers.getNodeType(node).binaryenType, emitList(node.truePart, document, parsingContext), node.falsePart ? emitList(node.falsePart, document, parsingContext) : []); | ||
} | ||
else if (node instanceof nodes_1.Nodes.ReferenceNode) { | ||
const instr = node.isLocal ? 'local.get' : 'global.get'; | ||
const local = node.getAnnotation(annotations_1.annotations.LocalIdentifier).local; | ||
return t.instruction(instr, [t.identifier(local.name)]); | ||
const ref = getReferencedSymbol(node); | ||
if (ref.type === 'VALUE') { | ||
const instr = node.isLocal ? 'local.get' : 'global.get'; | ||
return t.instruction(instr, [t.identifier(ref.symbol)]); | ||
} | ||
else if (ref.type === 'TABLE') { | ||
const index = parsingContext.getFunctionInTableNumber(ref.symbol); | ||
const numberLiteral = t.numberLiteralFromRaw(index, 'i32'); | ||
return t.objectInstruction('const', 'i32', [numberLiteral]); | ||
} | ||
} | ||
@@ -377,4 +450,11 @@ else if (node instanceof nodes_1.Nodes.MemberNode) { | ||
await wabt.ready; | ||
const wabtModule = wabt.parseWat(this.document.moduleName, text); | ||
let wabtModule; | ||
try { | ||
wabtModule = wabt.parseWat(this.document.moduleName, text); | ||
} | ||
catch (e) { | ||
console.log(text); | ||
throw e; | ||
} | ||
try { | ||
wabtModule.resolveNames(); | ||
@@ -522,3 +602,3 @@ wabtModule.validate(); | ||
const identifier = t.identifier(local.name); | ||
starters.push(t.instruction('global.set', [identifier, ...emitList($.decl.value, document)])); | ||
starters.push(t.instruction('global.set', [identifier, ...emitList($.decl.value, document, this.parsingContext)])); | ||
return t.global(t.globalType(binaryenType, mut), [t.objectInstruction('const', binaryenType, [t.numberLiteralFromRaw(0)])], // emitList($.decl.value, compilationPhase.document), | ||
@@ -538,3 +618,3 @@ identifier); | ||
else { | ||
createdFunctions.push(emitFunction(fun.functionNode, document)); | ||
createdFunctions.push(emitFunction(fun.functionNode, document, this.parsingContext)); | ||
} | ||
@@ -574,3 +654,17 @@ const exportedAnnotation = functionName.getAnnotation(annotations_1.annotations.Export); | ||
const starters = []; | ||
const tableElems = this.parsingContext.getOrderedTable(); | ||
this.parsingContext.signatures.forEach($ => moduleParts.push($)); | ||
const table = t.table('anyfunc', t.limit(tableElems.length), t.identifier('lys::internal-functions')); | ||
const elem = t.elem( | ||
// table | ||
t.indexLiteral(0), | ||
// offset | ||
[t.objectInstruction('const', 'i32', [t.numberLiteralFromRaw(0)])], | ||
// elems | ||
tableElems.map(x => t.identifier(x))); | ||
const memory = t.memory(t.limit(1), t.identifier('mem')); | ||
if (tableElems.length) { | ||
moduleParts.push(table); | ||
moduleParts.push(elem); | ||
} | ||
moduleParts.push(memory); | ||
@@ -577,0 +671,0 @@ moduleParts.push(t.moduleExport('memory', t.moduleExportDescr('Memory', t.identifier('mem')))); |
@@ -39,2 +39,3 @@ "use strict"; | ||
if (node.functionReturnType) { | ||
// TODO: dehardcode this... Unit type may be a good approach | ||
returnsVoidValue = | ||
@@ -41,0 +42,0 @@ node.functionReturnType instanceof nodes_1.Nodes.ReferenceNode && node.functionReturnType.variable.text === 'void'; |
@@ -24,4 +24,3 @@ import { Nodes } from './nodes'; | ||
export declare function areEqualTypes(typeA: Type | null | void, typeB: Type | null | void): boolean; | ||
export declare class FunctionType extends Type { | ||
name: Nodes.NameIdentifierNode; | ||
export declare class FunctionSignatureType extends Type { | ||
readonly nativeType: NativeTypes; | ||
@@ -31,3 +30,2 @@ readonly parameterTypes: Type[]; | ||
returnType?: Type; | ||
constructor(name: Nodes.NameIdentifierNode); | ||
canBeAssignedTo(type: Type, ctx: Scope): boolean; | ||
@@ -40,2 +38,14 @@ equals(type: Type): boolean; | ||
} | ||
export declare class FunctionType extends Type { | ||
name: Nodes.NameIdentifierNode; | ||
readonly nativeType: NativeTypes; | ||
readonly signature: FunctionSignatureType; | ||
constructor(name: Nodes.NameIdentifierNode); | ||
equals(type: Type): boolean; | ||
canBeAssignedTo(type: Type, ctx: Scope): boolean; | ||
toString(): string; | ||
inspect(_depth: number): string; | ||
schema(): {}; | ||
getSchemaValue(name: string): void; | ||
} | ||
export declare class StructType extends Type { | ||
@@ -42,0 +52,0 @@ parameters: Nodes.ParameterNode[]; |
@@ -17,2 +17,3 @@ "use strict"; | ||
switch (this.nativeType) { | ||
case NativeTypes.func: | ||
case NativeTypes.i32: | ||
@@ -24,3 +25,2 @@ return 'i32'; | ||
return 'f64'; | ||
case NativeTypes.func: | ||
case NativeTypes.i64: | ||
@@ -79,6 +79,5 @@ return 'i64'; | ||
exports.areEqualTypes = areEqualTypes; | ||
class FunctionType extends Type { | ||
constructor(name) { | ||
super(); | ||
this.name = name; | ||
class FunctionSignatureType extends Type { | ||
constructor() { | ||
super(...arguments); | ||
this.nativeType = NativeTypes.func; | ||
@@ -89,3 +88,3 @@ this.parameterTypes = []; | ||
canBeAssignedTo(type, ctx) { | ||
if (type instanceof FunctionType) { | ||
if (type instanceof FunctionSignatureType) { | ||
if (this.parameterTypes.length !== type.parameterTypes.length) | ||
@@ -115,6 +114,4 @@ return false; | ||
return false; | ||
if (!(type instanceof FunctionType)) | ||
if (!(type instanceof FunctionSignatureType)) | ||
return false; | ||
if (this.name !== type.name) | ||
return false; | ||
if (this.parameterTypes.length !== type.parameterTypes.length) | ||
@@ -129,5 +126,5 @@ return false; | ||
toString() { | ||
const params = this.parameterNames.map(($, ix) => { | ||
const type = this.parameterTypes && this.parameterTypes[ix]; | ||
return $ + ': ' + (type || '?'); | ||
const params = this.parameterTypes.map((type, ix) => { | ||
const name = this.parameterNames && this.parameterNames[ix]; | ||
return (name ? name + ': ' : '') + (type || '?'); | ||
}); | ||
@@ -137,4 +134,3 @@ return `fun(${params.join(', ')}) -> ${this.returnType ? this.returnType : '?'}`; | ||
inspect(_depth) { | ||
const params = this.parameterNames.map((_, ix) => { | ||
const type = this.parameterTypes && this.parameterTypes[ix]; | ||
const params = this.parameterTypes.map(type => { | ||
if (!type) { | ||
@@ -147,4 +143,54 @@ return '(?)'; | ||
}); | ||
return `(fun ${JSON.stringify(this.name.name)} (${params.join(' ')}) ${(this.returnType && | ||
this.returnType.inspect(0)) || | ||
return `(fun (${params.join(' ')}) ${(this.returnType && this.returnType.inspect(0)) || '?'})`; | ||
} | ||
schema() { | ||
return {}; | ||
} | ||
getSchemaValue(name) { | ||
throw new Error(`Cannot read schema property ${name} of ${this.inspect(10)}`); | ||
} | ||
} | ||
exports.FunctionSignatureType = FunctionSignatureType; | ||
class FunctionType extends Type { | ||
constructor(name) { | ||
super(); | ||
this.name = name; | ||
this.nativeType = NativeTypes.func; | ||
this.signature = new FunctionSignatureType(); | ||
} | ||
equals(type) { | ||
if (!type) | ||
return false; | ||
if (!(type instanceof FunctionType)) | ||
return false; | ||
if (this.name !== type.name) | ||
return false; | ||
if (!this.signature.equals(type.signature)) | ||
return false; | ||
return true; | ||
} | ||
canBeAssignedTo(type, ctx) { | ||
if (type instanceof FunctionType) { | ||
return this.signature.canBeAssignedTo(type.signature, ctx); | ||
} | ||
else if (type instanceof FunctionSignatureType) { | ||
return this.signature.canBeAssignedTo(type, ctx); | ||
} | ||
return false; | ||
} | ||
toString() { | ||
return this.signature.toString(); | ||
} | ||
inspect(_depth) { | ||
const params = this.signature.parameterNames.map((_, ix) => { | ||
const type = this.signature.parameterTypes && this.signature.parameterTypes[ix]; | ||
if (!type) { | ||
return '(?)'; | ||
} | ||
else { | ||
return type.inspect(0); | ||
} | ||
}); | ||
return `(fun ${JSON.stringify(this.name.name)} (${params.join(' ')}) ${(this.signature.returnType && | ||
this.signature.returnType.inspect(0)) || | ||
'?'})`; | ||
@@ -729,3 +775,3 @@ } | ||
const fn = getNonVoidFunction(TypeHelpers.getNodeType(prop.name), ctx); | ||
offset += fn.returnType.getSchemaValue('byteSize', ctx); | ||
offset += fn.signature.returnType.getSchemaValue('byteSize', ctx); | ||
} | ||
@@ -748,3 +794,3 @@ return offset; | ||
const fn = getNonVoidFunction(TypeHelpers.getNodeType(prop.name), ctx); | ||
offset += fn.returnType.getSchemaValue('stackSize', ctx); | ||
offset += fn.signature.returnType.getSchemaValue('stackSize', ctx); | ||
} | ||
@@ -755,3 +801,3 @@ return offset; | ||
const fn = getNonVoidFunction(TypeHelpers.getNodeType(property.name), ctx); | ||
return fn.returnType.getSchemaValue('allocationSize', ctx); | ||
return fn.signature.returnType.getSchemaValue('allocationSize', ctx); | ||
} | ||
@@ -851,3 +897,3 @@ } | ||
for (let fn of functions) { | ||
if (fn.returnType && !voidType.canBeAssignedTo(fn.returnType, ctx)) { | ||
if (fn.signature.returnType && !voidType.canBeAssignedTo(fn.signature.returnType, ctx)) { | ||
return fn; | ||
@@ -854,0 +900,0 @@ } |
@@ -8,5 +8,8 @@ "use strict"; | ||
} | ||
if (type instanceof types_1.FunctionType) { | ||
if (type instanceof types_1.FunctionSignatureType) { | ||
return isValidType(type.returnType) && type.parameterTypes.every(isValidType); | ||
} | ||
if (type instanceof types_1.FunctionType) { | ||
return isValidType(type.signature); | ||
} | ||
if (type instanceof types_1.TypeAlias) { | ||
@@ -13,0 +16,0 @@ return isValidType(type.of); |
@@ -22,5 +22,5 @@ "use strict"; | ||
} | ||
else if (node instanceof nodes_1.Nodes.FunctionParameterTypeNode) { | ||
if (node.name) { | ||
return `${printNode(node.name)}: ${printNode(node.parameterType)}`; | ||
else if (node instanceof nodes_1.Nodes.SignatureParameterNode) { | ||
if (node.parameterName) { | ||
return `${printNode(node.parameterName)}: ${printNode(node.parameterType)}`; | ||
} | ||
@@ -27,0 +27,0 @@ else { |
{ | ||
"name": "lys", | ||
"version": "0.1.11", | ||
"version": "0.1.12-20200206214526.commit-173e6f1", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
935027
10695