diff --git a/src/ast/base_language.nim b/src/ast/base_language.nim index db1f55dd..0e0cc5b3 100644 --- a/src/ast/base_language.nim +++ b/src/ast/base_language.nim @@ -507,14 +507,140 @@ typeComputers[functionDefinitionClass.id] = proc(ctx: ModelComputationContextBas continue functionType.add(IdFunctionTypeParameterTypes, parameterType) + # todo: this shouldn't set the model functionType.model = node.model functionType.forEach2 n: n.model = node.model - echo fmt"computed function type: {`$`(functionType, true)}" + debugf"computed function type: {`$`(functionType, true)}" return functionType +typeComputers[assignmentClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for assignment {node}" + return voidTypeInstance + +typeComputers[emptyClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for empty {node}" + return voidTypeInstance + +typeComputers[nodeListClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for node list {node}" + + if node.firstChild(IdNodeListChildren).getSome(childNode): + return ctx.computeType(childNode) + + return voidTypeInstance + +typeComputers[blockClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for block {node}" + + if node.firstChild(IdBlockChildren).getSome(childNode): + return ctx.computeType(childNode) + + return voidTypeInstance + +typeComputers[nodeReferenceClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for node reference {node}" + # todo + return voidTypeInstance + +typeComputers[breakClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for break {node}" + return voidTypeInstance + +typeComputers[continueClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for continue {node}" + return voidTypeInstance + +typeComputers[returnClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for return {node}" + return voidTypeInstance + +# binary expressions +typeComputers[addExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for add {node}" + return voidTypeInstance + +typeComputers[subExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for sub {node}" + return voidTypeInstance + +typeComputers[mulExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for mul {node}" + return voidTypeInstance + +typeComputers[divExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for div {node}" + return voidTypeInstance + +typeComputers[modExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for mod {node}" + return voidTypeInstance + +typeComputers[lessExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for less {node}" + return voidTypeInstance + +typeComputers[lessEqualExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for less equal {node}" + return voidTypeInstance + +typeComputers[greaterExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for greater {node}" + return voidTypeInstance + +typeComputers[greaterEqualExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for greater equal {node}" + return voidTypeInstance + +typeComputers[equalExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for equal {node}" + return voidTypeInstance + +typeComputers[notEqualExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for not equal {node}" + return voidTypeInstance + +typeComputers[andExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for and {node}" + return voidTypeInstance + +typeComputers[orExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for or {node}" + return voidTypeInstance + +typeComputers[orderExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for order {node}" + return voidTypeInstance + +# unary expressions +typeComputers[negateExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for negate {node}" + return voidTypeInstance + +typeComputers[notExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for not {node}" + return voidTypeInstance + +# calls +typeComputers[callClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for call {node}" + # todo + return voidTypeInstance + +typeComputers[appendStringExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for append string {node}" + return voidTypeInstance + +typeComputers[printExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for print {node}" + return voidTypeInstance + +typeComputers[buildExpressionClass.id] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute type for build {node}" + return voidTypeInstance + let baseLanguage* = newLanguage(IdBaseLanguage, @[ namedInterface, declarationInterface, diff --git a/src/ast/base_language_wasm.nim b/src/ast/base_language_wasm.nim index 2d1892a9..2ee1c72b 100644 --- a/src/ast/base_language_wasm.nim +++ b/src/ast/base_language_wasm.nim @@ -9,6 +9,8 @@ type BaseLanguageWasmCompiler* = ref object builder: WasmBuilder + ctx: ModelComputationContextBase + wasmFuncs: Table[Id, WasmFuncIdx] functionsToCompile: seq[(AstNode, WasmFuncIdx)] @@ -27,10 +29,11 @@ type proc setupGenerators(self: BaseLanguageWasmCompiler) -proc newBaseLanguageWasmCompiler*(): BaseLanguageWasmCompiler = +proc newBaseLanguageWasmCompiler*(ctx: ModelComputationContextBase): BaseLanguageWasmCompiler = new result result.setupGenerators() result.builder = newWasmBuilder() + result.ctx = ctx result.builder.mems.add(WasmMem(typ: WasmMemoryType(limits: WasmLimits(min: 255)))) diff --git a/src/ast/model.nim b/src/ast/model.nim index 166f2dca..2100f187 100644 --- a/src/ast/model.nim +++ b/src/ast/model.nim @@ -141,7 +141,7 @@ type id {.getter.}: LanguageId version {.getter.}: int classes {.getter.}: Table[ClassId, NodeClass] - childClasses {.getter.}: Table[ClassId, seq[NodeClass]] + # childClasses {.getter.}: Table[ClassId, seq[NodeClass]] builder {.getter.}: CellBuilder validators: Table[ClassId, NodeValidator] @@ -155,6 +155,7 @@ type languages {.getter.}: seq[Language] importedModels {.getter.}: seq[Model] classesToLanguages {.getter.}: Table[ModelId, Language] + childClasses {.getter.}: Table[ClassId, seq[NodeClass]] nodes {.getter.}: Table[NodeId, AstNode] onNodeDeleted*: Event[tuple[self: Model, parent: AstNode, child: AstNode, role: RoleId, index: int]] @@ -229,19 +230,19 @@ proc newLanguage*(id: LanguageId, classes: seq[NodeClass], builder: CellBuilder, for c in classes: result.classes[c.id] = c - if c.base.isNotNil: - if not result.childClasses.contains(c.base.id): - result.childClasses[c.base.id] = @[] - result.childClasses[c.base.id].add c + # if c.base.isNotNil: + # if not result.childClasses.contains(c.base.id): + # result.childClasses[c.base.id] = @[] + # result.childClasses[c.base.id].add c - for i in c.interfaces: - if not result.childClasses.contains(i.id): - result.childClasses[i.id] = @[] - result.childClasses[i.id].add c + # for i in c.interfaces: + # if not result.childClasses.contains(i.id): + # result.childClasses[i.id] = @[] + # result.childClasses[i.id].add c result.builder = builder -proc forEachChildClass*(self: Language, base: NodeClass, handler: proc(c: NodeClass)) = +proc forEachChildClass*(self: Model, base: NodeClass, handler: proc(c: NodeClass)) = handler(base) if self.childClasses.contains(base.id): for c in self.childClasses[base.id]: @@ -267,10 +268,23 @@ proc addModel*(self: Project, model: Model) = proc addLanguage*(self: Model, language: Language) = if not language.verify(): return + self.languages.add language + for c in language.classes.keys: self.classesToLanguages[c] = language + for c in language.classes.values: + if c.base.isNotNil: + if not self.childClasses.contains(c.base.id): + self.childClasses[c.base.id] = @[] + self.childClasses[c.base.id].add c + + for i in c.interfaces: + if not self.childClasses.contains(i.id): + self.childClasses[i.id] = @[] + self.childClasses[i.id].add c + proc addRootNode*(self: Model, node: AstNode) = self.rootNodes.add node # node.forEach proc(n: AstNode) = @@ -418,6 +432,14 @@ proc firstChild*(node: AstNode, role: RoleId): Option[AstNode] = result = c.nodes[0].some break +proc lastChild*(node: AstNode, role: RoleId): Option[AstNode] = + result = AstNode.none + for c in node.childLists.mitems: + if c.role == role: + if c.nodes.len > 0: + result = c.nodes.last.some + break + proc hasReference*(node: AstNode, role: RoleId): bool = result = false for c in node.references: @@ -508,15 +530,17 @@ proc newAstNode*(class: NodeClass, id: Option[NodeId] = NodeId.none): AstNode = result.class = class.id result.addMissingFieldsForClass(class) -proc isUnique*(language: Language, class: NodeClass): bool = +proc isUnique*(model: Model, class: NodeClass): bool = if class.isFinal: return true - if not language.childClasses.contains(class.id): + if not model.childClasses.contains(class.id): return true return false -proc fillDefaultChildren*(node: AstNode, language: Language, onlyUnique: bool = false) = +proc fillDefaultChildren*(node: AstNode, model: Model, onlyUnique: bool = false) = + let language = model.classesToLanguages.getOrDefault(node.class, nil) let class = language.classes.getOrDefault(node.class, nil) + for desc in class.children: if desc.count in {ChildCount.One, ChildCount.OneOrMore}: let childClass = language.classes.getOrDefault(desc.class) @@ -524,12 +548,12 @@ proc fillDefaultChildren*(node: AstNode, language: Language, onlyUnique: bool = log lvlError, fmt"Unknown class {desc.class}" continue - let isUnique = language.isUnique(childClass) + let isUnique = model.isUnique(childClass) if onlyUnique and not isUnique: continue let child = newAstNode(childClass) - child.fillDefaultChildren(language, onlyUnique) + child.fillDefaultChildren(model, onlyUnique) node.add(desc.id, child) proc ancestor*(node: AstNode, distance: int): AstNode = @@ -713,7 +737,7 @@ proc replaceWithDefault*(node: AstNode, fillDefaultChildren: bool = false): Opti var child = newAstNode(node.model.resolveClass(desc.class)) if fillDefaultChildren: - child.fillDefaultChildren(node.language) + child.fillDefaultChildren(node.model) # debugf"replaceWithDefault: replacing {node} with {child}" node.parent.replace(node.role, node.index, child) @@ -730,7 +754,7 @@ proc deleteOrReplaceWithDefault*(node: AstNode, fillDefaultChildren: bool = fals if desc.count in {One, OneOrMore} and node.parent.childCount(node.role) == 1: var child = newAstNode(node.model.resolveClass(desc.class)) if fillDefaultChildren: - child.fillDefaultChildren(node.language) + child.fillDefaultChildren(node.model) # debugf"deleteOrReplaceWithDefault: replacing {node} with {child}" node.parent.replace(node.role, node.index, child) @@ -748,7 +772,7 @@ proc insertDefaultNode*(node: AstNode, role: RoleId, index: int, fillDefaultChil let class = node.nodeClass let desc = class.nodeChildDescription(role).get - let language = node.language + let language = node.model.classesToLanguages.getOrDefault(desc.class, nil) if language.isNil: return @@ -758,7 +782,7 @@ proc insertDefaultNode*(node: AstNode, role: RoleId, index: int, fillDefaultChil var child = newAstNode(childClass) if fillDefaultChildren: - child.fillDefaultChildren(language) + child.fillDefaultChildren(node.model) node.insert(role, index, child) diff --git a/src/model_document.nim b/src/model_document.nim index 84dfe48f..d9ecce08 100644 --- a/src/model_document.nim +++ b/src/model_document.nim @@ -563,16 +563,15 @@ proc updateCompletions(self: ModelDocumentEditor) = debugf"updateCompletions {node}, {node.model.isNotNil}, {slotClass.name}" - for language in model.languages: - language.forEachChildClass slotClass, proc(childClass: NodeClass) = - if self.getSubstitutionsForClass(targetCell, childClass, (c) -> void => self.unfilteredCompletions.add(c)): - return + model.forEachChildClass slotClass, proc(childClass: NodeClass) = + if self.getSubstitutionsForClass(targetCell, childClass, (c) -> void => self.unfilteredCompletions.add(c)): + return - if childClass.isAbstract or childClass.isInterface: - return + if childClass.isAbstract or childClass.isInterface: + return - let name = if childClass.alias.len > 0: childClass.alias else: childClass.name - self.unfilteredCompletions.add ModelCompletion(kind: ModelCompletionKind.SubstituteClass, name: name, class: childClass, parent: parent, role: role, index: index) + let name = if childClass.alias.len > 0: childClass.alias else: childClass.name + self.unfilteredCompletions.add ModelCompletion(kind: ModelCompletionKind.SubstituteClass, name: name, class: childClass, parent: parent, role: role, index: index) self.refilterCompletions() self.markDirty() @@ -2473,7 +2472,7 @@ proc applySelectedCompletion*(self: ModelDocumentEditor) {.expose("editor.model" parent.remove(role, index) var newNode = newAstNode(completion.class) - newNode.fillDefaultChildren(parent.language, true) + newNode.fillDefaultChildren(parent.model, true) parent.insert(role, index, newNode) self.rebuildCells() self.cursor = self.getFirstEditableCellOfNode(newNode).get @@ -2522,7 +2521,7 @@ proc runSelectedFunctionAsync*(self: ModelDocumentEditor): Future[void] {.async. self.document.ctx.state.updateNode(function.get) let typ = self.document.ctx.computeType(function.get) - echo `$`(typ, true) + log lvlDebug, `$`(typ, true) if function.get.childCount(IdFunctionDefinitionParameters) > 0: log(lvlError, fmt"Can't call function with parameters") @@ -2535,7 +2534,7 @@ proc runSelectedFunctionAsync*(self: ModelDocumentEditor): Future[void] {.async. "" measureBlock fmt"Compile '{name}' to wasm": - var compiler = newBaseLanguageWasmCompiler() + var compiler = newBaseLanguageWasmCompiler(self.document.ctx) let binary = compiler.compileToBinary(function.get) if self.document.workspace.getSome(workspace):