@composita/compiler
Version:
Composita language compiler.
118 lines • 6.94 kB
JavaScript
import { IL, ComponentDescriptor, ImplementationDescriptor, ProcedureDescriptor, VariableDescriptor, InterfaceDescriptor, MessageDescriptor, TextDescriptor, IntegerDescriptor, } from '@composita/il';
import { ComponentSymbol, BuiltInTypeSymbol, InterfaceSymbol, } from '../symbols/symbols';
import { ComponentGeneratorVisitor } from './code-generator';
import { Metadata } from './metadata';
import { ComponentNode } from '../ast/ast';
export class Generator {
generate(symbols) {
const il = new IL();
const metadata = this.generateMetadata(symbols);
//metadata.findMessage(symbols.finishMessage);
//metadata.findMessage(symbols.finishMessage);
symbols.components.forEach((component) => this.generateComponent(component, symbols, il, metadata));
return il;
}
generateMetadata(symbols) {
const metadata = new Metadata();
metadata.pushComponent(symbols.anyComponentType, new ComponentDescriptor(symbols.anyComponentType.identifier));
metadata.pushInterface(symbols.anyRequiredInterfaceType, new InterfaceDescriptor(symbols.anyRequiredInterfaceType.identifier));
metadata.pushMessage(symbols.finishMessage, new MessageDescriptor(symbols.finishMessage.identifier));
metadata.pushMessage(symbols.anyMessage, new MessageDescriptor(symbols.anyMessage.identifier));
symbols.getSystemProcedures().forEach((procedure) => {
const descriptor = new ProcedureDescriptor(procedure.identifier, undefined);
descriptor.parameters.push(...procedure.parameters.map((type) => {
return new VariableDescriptor(type.identifier, this.convertSymbolToDescriptor(type, metadata), true);
}));
metadata.pushProcedure(procedure, descriptor);
});
symbols.interfaces.forEach((symbol) => metadata.pushInterface(symbol, new InterfaceDescriptor(symbol.identifier)));
symbols.components.forEach((component) => metadata.pushComponent(component, new ComponentDescriptor(component.identifier)));
symbols.messages.forEach((symbol) => {
const message = new MessageDescriptor(symbol.identifier);
symbol.parameters.forEach((value) => {
message.data.push(this.convertSymbolToDescriptor(value, metadata));
});
metadata.pushMessage(symbol, message);
});
symbols.interfaces.forEach((component) => this.fillInterface(component, metadata, symbols));
symbols.impplementations.forEach((implementation) => {
const implementationDescriptor = new ImplementationDescriptor(metadata.findInterface(implementation.interfaceSymbol));
metadata.pushImplementation(implementation, implementationDescriptor);
});
symbols.variables.forEach((variable) => {
const typeDescriptor = this.convertSymbolToDescriptor(variable.type, metadata);
const varDescriptor = new VariableDescriptor(variable.identifier, typeDescriptor, true);
if (typeDescriptor instanceof TextDescriptor) {
varDescriptor.indexTypes.push(new IntegerDescriptor());
}
metadata.pushVariable(variable, varDescriptor);
});
symbols.collectionVariables.forEach((variable) => {
const typeDescriptor = this.convertSymbolToDescriptor(variable.type, metadata);
const varDescriptor = new VariableDescriptor(variable.identifier, typeDescriptor, true);
varDescriptor.indexTypes.push(...variable.parameters.map((type) => this.convertSymbolToDescriptor(type, metadata)));
metadata.pushVariable(variable, varDescriptor);
});
symbols.procedures.forEach((procedure) => {
const returnType = procedure.returnType;
const returnTypeDescriptor = returnType === symbols.voidType ? undefined : this.convertSymbolToDescriptor(returnType, metadata);
const procedureDescriptor = new ProcedureDescriptor(procedure.identifier, returnTypeDescriptor);
procedureDescriptor.parameters.push(...procedure.parameters.map((type) => {
return new VariableDescriptor(type.identifier, this.convertSymbolToDescriptor(type, metadata), true);
}));
metadata.pushProcedure(procedure, procedureDescriptor);
});
symbols.components.forEach((component) => this.fillComponent(component, metadata, symbols));
return metadata;
}
convertSymbolToDescriptor(symbol, metadata) {
if (symbol instanceof BuiltInTypeSymbol) {
return metadata.builtInTypeDescriptor(symbol);
}
if (symbol instanceof ComponentSymbol) {
return metadata.findComponent(symbol);
}
if (symbol instanceof InterfaceSymbol) {
return metadata.findInterface(symbol);
}
throw new Error('Cannot convert to descriptor');
}
fillInterface(interfaceSymbol, metadata, symbols) {
// TODO
metadata.findInterface(interfaceSymbol);
symbols;
}
static fillDeclarations(declarations, symbol, metadata, symbols) {
symbols
.getVariables(symbol)
.forEach((variable) => declarations.variables.push(metadata.findVariable(variable)));
symbols
.getCollectionVariables(symbol)
.forEach((variable) => declarations.variables.push(metadata.findVariable(variable)));
symbols
.getProcedures(symbol)
.forEach((procedure) => declarations.procedures.push(metadata.findProcedure(procedure)));
}
fillComponent(component, metadata, symbols) {
const descriptor = metadata.findComponent(component);
component.genericType.offered.forEach((interfaceDeclaration) => descriptor.offers.push(metadata.findInterface(interfaceDeclaration.interfaceSymbol)));
component.genericType.required.forEach((interfaceDeclaration) => descriptor.requires.push(metadata.findInterface(interfaceDeclaration.interfaceSymbol)));
symbols
.getImplementations(component)
.forEach((implementation) => descriptor.implementations.push(metadata.findImplementation(implementation)));
Generator.fillDeclarations(descriptor.declarations, component, metadata, symbols);
}
generateComponent(component, symbols, il, metadata) {
const node = symbols.symbolToComponent.get(component);
if (node === undefined || !(node instanceof ComponentNode)) {
throw new Error(`Failed node lookup for component ${component.identifier}`);
}
node.getBody()?.accept(new ComponentGeneratorVisitor(component, metadata, symbols));
const descriptor = metadata.findComponent(component);
il.components.push(descriptor);
if (component.isEntryPoint) {
il.entryPoints.push(descriptor);
}
}
}
//# sourceMappingURL=generator.js.map