From 5d48acc1a64817d3bad99c00427f058d7b598cac Mon Sep 17 00:00:00 2001 From: Nimaoth Date: Thu, 30 Nov 2023 21:13:46 +0100 Subject: [PATCH] more progress on lang lang --- model/test-language.ast-model | 409 ++++++++++++++++++--------- scripting/absytree_internal.nim | 9 + scripting/absytree_internal_wasm.nim | 6 + scripting/editor_model_api.nim | 6 + scripting/editor_model_api_wasm.nim | 52 ++++ src/ast/lang/lang_language.nim | 151 +++++++++- src/ast_ids.nim | 9 +- src/model_document.nim | 42 ++- 8 files changed, 529 insertions(+), 155 deletions(-) diff --git a/model/test-language.ast-model b/model/test-language.ast-model index ca12d4d7..dd51ab51 100644 --- a/model/test-language.ast-model +++ b/model/test-language.ast-model @@ -6,197 +6,336 @@ "models": [], "rootNodes": [ { - "id": "1c3ba37d1073b1226b9ee06b", - "class": "654fbb281446e19b3822522a", - "properties": [ - [ - "62e5339c564d29f772934529", - "Expression" - ], - [ - "654fbb281446e19b38225236", - false - ], - [ - "654fbb281446e19b38225239", - false - ] - ], + "id": "654fbb281446e19b38225264", + "class": "654fbb281446e19b3822524f", "children": [ [ - "654fbb281446e19b38225237", + "654fbb281446e19b38225250", [ { - "id": "1c73943084dd113e5b791530", - "class": "654fbb281446e19b38225241", - "references": [ + "id": "21b0810be06ab5607dd26759", + "class": "654fbb281446e19b3822522a", + "properties": [ [ - "654fbb281446e19b38225242", - "1c3ba37d1073b1226b9ee06b" - ] - ] - } - ] - ], - [ - "654fbb281446e19b3822523a", - [ - { - "id": "1c7380ef84dd113e5b791405", - "class": "654fbb281446e19b38225241", - "references": [ + "62e5339c564d29f772934529", + "CellBuilder" + ], [ - "654fbb281446e19b38225242", - "1c3ba37d1073b1226b9ee06b" - ] - ] - }, - { - "id": "1c73833184dd113e5b791440", - "class": "654fbb281446e19b38225241", - "references": [ + "654fbb281446e19b38225238", + "" + ], [ - "654fbb281446e19b38225242", - "1c3ba37d1073b1226b9ee06b" - ] - ] - } - ] - ], - [ - "654fbb281446e19b3822522c", - [ - { - "id": "1c45bbd9e60b0d1352276921", - "class": "654fbb281446e19b38225230", - "properties": [ + "654fbb281446e19b38225236", + false + ], [ - "62e5339c564d29f772934529", - "xvlc" + "654fbb281446e19b38225239", + false + ], + [ + "654fbb281446e19b38225248", + false + ], + [ + "654fbb281446e19b3822524b", + false + ], + [ + "654fbb281446e19b3822524a", + 0 ] ], "children": [ [ - "654fbb281446e19b38225231", + "654fbb281446e19b38225237", + [] + ], + [ + "654fbb281446e19b3822523a", + [] + ], + [ + "654fbb281446e19b3822522b", + [] + ], + [ + "654fbb281446e19b3822522c", + [] + ], + [ + "654fbb281446e19b3822522d", [ { - "id": "1c45bbd9e60b0d1352276922", - "class": "654fbb281446e19b38225241", - "references": [ + "id": "21b1b4d2382ec64408d523eb", + "class": "654fbb281446e19b38225233", + "properties": [ [ - "654fbb281446e19b38225242", - "1c3ba37d1073b1226b9ee06b" + "62e5339c564d29f772934529", + "targetClass" + ] + ], + "children": [ + [ + "654fbb281446e19b38225234", + [ + { + "id": "21b1b4d2382ec64408d523ec", + "class": "654fbb281446e19b38225241", + "references": [ + [ + "654fbb281446e19b38225242", + "1c3ba37d1073b1226b9ee06b" + ] + ] + } + ] + ], + [ + "654fbb281446e19b38225235", + [ + { + "id": "21b3fe38dade85465522ed18", + "class": "654fbb281446e19b38225245" + } + ] ] ] } ] + ], + [ + "654fbb281446e19b38225249", + [] ] ] - } - ] - ], - [ - "654fbb281446e19b3822522b", - [ + }, { - "id": "1c3c25ef1073b1226b9ee0a6", - "class": "654fbb281446e19b3822522e", + "id": "1c3ba37d1073b1226b9ee06b", + "class": "654fbb281446e19b3822522a", "properties": [ [ "62e5339c564d29f772934529", - "left" + "Expressin" + ], + [ + "654fbb281446e19b38225238", + "hello" + ], + [ + "654fbb281446e19b38225236", + true + ], + [ + "654fbb281446e19b38225239", + true + ], + [ + "654fbb281446e19b38225248", + true + ], + [ + "654fbb281446e19b3822524b", + true + ], + [ + "654fbb281446e19b3822524a", + 10 ] ], "children": [ [ - "654fbb281446e19b3822522f", + "654fbb281446e19b38225237", [ { - "id": "1c744ac74dff7403658c5044", - "class": "654fbb281446e19b3822523c" + "id": "1c73943084dd113e5b791530", + "class": "654fbb281446e19b38225241", + "references": [ + [ + "654fbb281446e19b38225242", + "1c3ba37d1073b1226b9ee06b" + ] + ] } ] - ] - ] - }, - { - "id": "1c3c47f11073b1226b9ee115", - "class": "654fbb281446e19b3822522e", - "properties": [ - [ - "62e5339c564d29f772934529", - "right" - ] - ], - "children": [ + ], [ - "654fbb281446e19b3822522f", + "654fbb281446e19b3822523a", [ { - "id": "1c74514f4dff7403658c5081", - "class": "654fbb281446e19b3822523d" + "id": "1c7380ef84dd113e5b791405", + "class": "654fbb281446e19b38225241", + "references": [ + [ + "654fbb281446e19b38225242", + "1c3ba37d1073b1226b9ee06b" + ] + ] + }, + { + "id": "1c73833184dd113e5b791440", + "class": "654fbb281446e19b38225241", + "references": [ + [ + "654fbb281446e19b38225242", + "1c3ba37d1073b1226b9ee06b" + ] + ] } ] - ] - ] - }, - { - "id": "1c401636e2172031051e796a", - "class": "654fbb281446e19b3822522e", - "properties": [ - [ - "62e5339c564d29f772934529", - "top" - ] - ], - "children": [ + ], [ - "654fbb281446e19b3822522f", + "654fbb281446e19b3822522b", [ { - "id": "1c7458c74dff7403658c50be", - "class": "654fbb281446e19b3822523e" + "id": "1c3c25ef1073b1226b9ee0a6", + "class": "654fbb281446e19b3822522e", + "properties": [ + [ + "62e5339c564d29f772934529", + "left" + ] + ], + "children": [ + [ + "654fbb281446e19b3822522f", + [ + { + "id": "1c744ac74dff7403658c5044", + "class": "654fbb281446e19b3822523c" + } + ] + ] + ] + }, + { + "id": "1c3c47f11073b1226b9ee115", + "class": "654fbb281446e19b3822522e", + "properties": [ + [ + "62e5339c564d29f772934529", + "right" + ] + ], + "children": [ + [ + "654fbb281446e19b3822522f", + [ + { + "id": "1c74514f4dff7403658c5081", + "class": "654fbb281446e19b3822523d" + } + ] + ] + ] + }, + { + "id": "1c401636e2172031051e796a", + "class": "654fbb281446e19b3822522e", + "properties": [ + [ + "62e5339c564d29f772934529", + "top" + ] + ], + "children": [ + [ + "654fbb281446e19b3822522f", + [ + { + "id": "1c7458c74dff7403658c50be", + "class": "654fbb281446e19b3822523e" + } + ] + ] + ] } ] - ] - ] - } - ] - ], - [ - "654fbb281446e19b3822522d", - [ - { - "id": "1c457f81e60b0d13522767f5", - "class": "654fbb281446e19b38225233", - "properties": [ + ], [ - "62e5339c564d29f772934529", - "uiae" - ] - ], - "children": [ + "654fbb281446e19b3822522c", + [ + { + "id": "1c45bbd9e60b0d1352276921", + "class": "654fbb281446e19b38225230", + "properties": [ + [ + "62e5339c564d29f772934529", + "xvlc" + ] + ], + "children": [ + [ + "654fbb281446e19b38225231", + [ + { + "id": "1c45bbd9e60b0d1352276922", + "class": "654fbb281446e19b38225241", + "references": [ + [ + "654fbb281446e19b38225242", + "1c3ba37d1073b1226b9ee06b" + ] + ] + } + ] + ] + ] + } + ] + ], [ - "654fbb281446e19b38225234", + "654fbb281446e19b3822522d", [ { - "id": "1c457f81e60b0d13522767f6", - "class": "654fbb281446e19b38225241", - "references": [ + "id": "1c457f81e60b0d13522767f5", + "class": "654fbb281446e19b38225233", + "properties": [ [ - "654fbb281446e19b38225242", - "1c3ba37d1073b1226b9ee06b" + "62e5339c564d29f772934529", + "uiae" + ] + ], + "children": [ + [ + "654fbb281446e19b38225234", + [ + { + "id": "1c457f81e60b0d13522767f6", + "class": "654fbb281446e19b38225241", + "references": [ + [ + "654fbb281446e19b38225242", + "1c3ba37d1073b1226b9ee06b" + ] + ] + } + ] + ], + [ + "654fbb281446e19b38225235", + [ + { + "id": "1c7375e884dd113e5b7913ca", + "class": "654fbb281446e19b38225247" + } + ] ] ] } ] ], [ - "654fbb281446e19b38225235", + "654fbb281446e19b38225249", [ { - "id": "1c7375e884dd113e5b7913ca", - "class": "654fbb281446e19b38225247" + "id": "2175d5b6f19f3b424661c6a8", + "class": "654fbb281446e19b3822524d", + "references": [ + [ + "654fbb281446e19b3822524e", + "1c3c25ef1073b1226b9ee0a6" + ] + ] } ] ] diff --git a/scripting/absytree_internal.nim b/scripting/absytree_internal.nim index 9fca1158..8b0b2ce6 100644 --- a/scripting/absytree_internal.nim +++ b/scripting/absytree_internal.nim @@ -281,6 +281,12 @@ proc editor_model_getContextWithMode_string_ModelDocumentEditor_string_impl*( proc editor_model_isThickCursor_bool_ModelDocumentEditor_impl*( self: ModelDocumentEditor): bool = discard +proc editor_model_gotoDefinition_void_ModelDocumentEditor_bool_impl*( + self: ModelDocumentEditor; select: bool = false) = + discard +proc editor_model_toggleBoolCell_void_ModelDocumentEditor_bool_impl*( + self: ModelDocumentEditor; select: bool = false) = + discard proc editor_model_moveCursorLeft_void_ModelDocumentEditor_bool_impl*( self: ModelDocumentEditor; select: bool = false) = discard @@ -393,6 +399,9 @@ proc editor_model_addRootNode_void_ModelDocumentEditor_impl*( proc editor_model_saveProject_void_ModelDocumentEditor_impl*( self: ModelDocumentEditor) = discard +proc editor_model_loadBaseLanguageModel_void_ModelDocumentEditor_impl*( + self: ModelDocumentEditor) = + discard proc editor_getBackend_Backend_App_impl*(): Backend = discard proc editor_toggleShowDrawnNodes_void_App_impl*() = diff --git a/scripting/absytree_internal_wasm.nim b/scripting/absytree_internal_wasm.nim index 75cdea33..cc22ded8 100644 --- a/scripting/absytree_internal_wasm.nim +++ b/scripting/absytree_internal_wasm.nim @@ -189,6 +189,10 @@ proc editor_model_getContextWithMode_string_ModelDocumentEditor_string_impl( self: ModelDocumentEditor; context: string): string {.importc.} proc editor_model_isThickCursor_bool_ModelDocumentEditor_impl( self: ModelDocumentEditor): bool {.importc.} +proc editor_model_gotoDefinition_void_ModelDocumentEditor_bool_impl( + self: ModelDocumentEditor; select: bool = false) {.importc.} +proc editor_model_toggleBoolCell_void_ModelDocumentEditor_bool_impl( + self: ModelDocumentEditor; select: bool = false) {.importc.} proc editor_model_moveCursorLeft_void_ModelDocumentEditor_bool_impl( self: ModelDocumentEditor; select: bool = false) {.importc.} proc editor_model_moveCursorRight_void_ModelDocumentEditor_bool_impl( @@ -263,6 +267,8 @@ proc editor_model_addRootNode_void_ModelDocumentEditor_impl( self: ModelDocumentEditor) {.importc.} proc editor_model_saveProject_void_ModelDocumentEditor_impl( self: ModelDocumentEditor) {.importc.} +proc editor_model_loadBaseLanguageModel_void_ModelDocumentEditor_impl( + self: ModelDocumentEditor) {.importc.} proc editor_getBackend_Backend_App_impl(): Backend {.importc.} proc editor_toggleShowDrawnNodes_void_App_impl() {.importc.} proc editor_saveAppState_void_App_impl() {.importc.} diff --git a/scripting/editor_model_api.nim b/scripting/editor_model_api.nim index 4cd5b183..2b4e7f10 100644 --- a/scripting/editor_model_api.nim +++ b/scripting/editor_model_api.nim @@ -23,6 +23,10 @@ proc getContextWithMode*(self: ModelDocumentEditor; context: string): string = context) proc isThickCursor*(self: ModelDocumentEditor): bool = editor_model_isThickCursor_bool_ModelDocumentEditor_impl(self) +proc gotoDefinition*(self: ModelDocumentEditor; select: bool = false) = + editor_model_gotoDefinition_void_ModelDocumentEditor_bool_impl(self, select) +proc toggleBoolCell*(self: ModelDocumentEditor; select: bool = false) = + editor_model_toggleBoolCell_void_ModelDocumentEditor_bool_impl(self, select) proc moveCursorLeft*(self: ModelDocumentEditor; select: bool = false) = editor_model_moveCursorLeft_void_ModelDocumentEditor_bool_impl(self, select) proc moveCursorRight*(self: ModelDocumentEditor; select: bool = false) = @@ -109,3 +113,5 @@ proc addRootNode*(self: ModelDocumentEditor) = editor_model_addRootNode_void_ModelDocumentEditor_impl(self) proc saveProject*(self: ModelDocumentEditor) = editor_model_saveProject_void_ModelDocumentEditor_impl(self) +proc loadBaseLanguageModel*(self: ModelDocumentEditor) = + editor_model_loadBaseLanguageModel_void_ModelDocumentEditor_impl(self) diff --git a/scripting/editor_model_api_wasm.nim b/scripting/editor_model_api_wasm.nim index 12d9c6ef..5d8ca58e 100644 --- a/scripting/editor_model_api_wasm.nim +++ b/scripting/editor_model_api_wasm.nim @@ -111,6 +111,44 @@ proc isThickCursor*(self: ModelDocumentEditor): bool = result = parseJson($res).jsonTo(typeof(result)) +proc editor_model_gotoDefinition_void_ModelDocumentEditor_bool_wasm(arg: cstring): cstring {. + importc.} +proc gotoDefinition*(self: ModelDocumentEditor; select: bool = false) = + var argsJson = newJArray() + argsJson.add block: + when ModelDocumentEditor is JsonNode: + self + else: + self.toJson() + argsJson.add block: + when bool is JsonNode: + select + else: + select.toJson() + let argsJsonString = $argsJson + let res {.used.} = editor_model_gotoDefinition_void_ModelDocumentEditor_bool_wasm( + argsJsonString.cstring) + + +proc editor_model_toggleBoolCell_void_ModelDocumentEditor_bool_wasm(arg: cstring): cstring {. + importc.} +proc toggleBoolCell*(self: ModelDocumentEditor; select: bool = false) = + var argsJson = newJArray() + argsJson.add block: + when ModelDocumentEditor is JsonNode: + self + else: + self.toJson() + argsJson.add block: + when bool is JsonNode: + select + else: + select.toJson() + let argsJsonString = $argsJson + let res {.used.} = editor_model_toggleBoolCell_void_ModelDocumentEditor_bool_wasm( + argsJsonString.cstring) + + proc editor_model_moveCursorLeft_void_ModelDocumentEditor_bool_wasm(arg: cstring): cstring {. importc.} proc moveCursorLeft*(self: ModelDocumentEditor; select: bool = false) = @@ -723,3 +761,17 @@ proc saveProject*(self: ModelDocumentEditor) = let res {.used.} = editor_model_saveProject_void_ModelDocumentEditor_wasm( argsJsonString.cstring) + +proc editor_model_loadBaseLanguageModel_void_ModelDocumentEditor_wasm( + arg: cstring): cstring {.importc.} +proc loadBaseLanguageModel*(self: ModelDocumentEditor) = + var argsJson = newJArray() + argsJson.add block: + when ModelDocumentEditor is JsonNode: + self + else: + self.toJson() + let argsJsonString = $argsJson + let res {.used.} = editor_model_loadBaseLanguageModel_void_ModelDocumentEditor_wasm( + argsJsonString.cstring) + diff --git a/src/ast/lang/lang_language.nim b/src/ast/lang/lang_language.nim index d505aa30..504db99c 100644 --- a/src/ast/lang/lang_language.nim +++ b/src/ast/lang/lang_language.nim @@ -47,8 +47,14 @@ let childrenDefinitionClass* = newNodeClass(IdChildrenDefinition, "ChildrenDefin NodeChildDescription(id: IdChildrenDefinitionCount, role: "count", class: IdCount, count: ChildCount.One), ]) -let classDefinitionClass* = newNodeClass(IdClassDefinition, "ClassDefinition", alias="class", interfaces=[namedInterface], canBeRoot=true, +let langAspectClass* = newNodeClass(IdLangAspect, "LangAspect", isAbstract=true) + +let langRootClass* = newNodeClass(IdLangRoot, "LangRoot", canBeRoot=true, + children=[NodeChildDescription(id: IdLangRootChildren, role: "children", class: IdLangAspect, count: ChildCount.ZeroOrMore)]) + +let classDefinitionClass* = newNodeClass(IdClassDefinition, "ClassDefinition", alias="class", base=langAspectClass, interfaces=[namedInterface], properties=[ + PropertyDescription(id: IdClassDefinitionAlias, role: "alias", typ: PropertyType.String), PropertyDescription(id: IdClassDefinitionAbstract, role: "abstract", typ: PropertyType.Bool), PropertyDescription(id: IdClassDefinitionInterface, role: "interface", typ: PropertyType.Bool), PropertyDescription(id: IdClassDefinitionFinal, role: "final", typ: PropertyType.Bool), @@ -128,6 +134,21 @@ builder.addBuilderFor IdChildrenDefinition, idNone(), proc(builder: CellBuilder, return cell +builder.addBuilderFor IdLangRoot, idNone(), proc(builder: CellBuilder, node: AstNode): Cell = + var cell = CollectionCell(id: newId().CellId, node: node, uiFlags: &{LayoutVertical}) + cell.fillChildren = proc(map: NodeCellMap) = + cell.add block: + buildChildrenT(builder, map, node, IdLangRootChildren, &{LayoutVertical}, 0.CellFlags): + separator: ConstantCell(node: node, text: "", disableEditing: true, disableSelection: true) + placeholder: "..." + + return cell + +builder.addBuilderFor IdLangAspect, idNone(), proc(builder: CellBuilder, node: AstNode): Cell = + # return PlaceholderCell(id: newId().CellId, node: node, role: IdClassReferenceTarget, shadowText: "") + var cell = ConstantCell(id: newId().CellId, node: node, shadowText: "...", themeBackgroundColors: @["&inputValidation.errorBackground", "&debugConsole.errorForeground"]) + return cell + builder.addBuilderFor IdClassDefinition, idNone(), proc(builder: CellBuilder, node: AstNode): Cell = var cell = CollectionCell(id: newId().CellId, node: node, uiFlags: &{LayoutHorizontal}) cell.fillChildren = proc(map: NodeCellMap) = @@ -150,6 +171,10 @@ builder.addBuilderFor IdClassDefinition, idNone(), proc(builder: CellBuilder, no var vertCell = CollectionCell(id: newId().CellId, node: node, uiFlags: &{LayoutVertical}, flags: &{OnNewLine, IndentChildren}) + vertCell.addHorizontal(node, 0.CellFlags): + sub.add ConstantCell(node: node, text: "alias", themeForegroundColors: @["keyword"], disableEditing: true) + sub.add PropertyCell(id: newId().CellId, node: node, property: IdClassDefinitionAlias, themeForegroundColors: @["variable"]) + vertCell.addHorizontal(node, 0.CellFlags): sub.add ConstantCell(node: node, text: "abstract", themeForegroundColors: @["keyword"], disableEditing: true) sub.add PropertyCell(id: newId().CellId, node: node, property: IdClassDefinitionAbstract, themeForegroundColors: @["variable"]) @@ -246,13 +271,15 @@ scopeComputers[IdClassReference] = proc(ctx: ModelComputationContextBase, node: echo "model ", model.id for root in model.rootNodes: echo "import root ", root - if root.class == IdClassDefinition: - nodes.add root + for _, aspect in root.children(IdLangRootChildren): + if aspect.class == IdClassDefinition: + nodes.add aspect for root in node.model.rootNodes: echo "root ", root - if root.class == IdClassDefinition: - nodes.add root + for _, aspect in root.children(IdLangRootChildren): + if aspect.class == IdClassDefinition: + nodes.add aspect return nodes @@ -263,12 +290,14 @@ scopeComputers[IdClassDefinition] = proc(ctx: ModelComputationContextBase, node: # todo: improve this for model in node.model.models: for root in model.rootNodes: - if root.class == IdClassDefinition: - nodes.add root + for _, aspect in root.children(IdLangRootChildren): + if aspect.class == IdClassDefinition: + nodes.add aspect for root in node.model.rootNodes: - if root.class == IdClassDefinition: - nodes.add root + for _, aspect in root.children(IdLangRootChildren): + if aspect.class == IdClassDefinition: + nodes.add aspect for _, prop in node.children(IdClassDefinitionProperties): nodes.add prop @@ -305,6 +334,7 @@ scopeComputers[IdRoleReference] = proc(ctx: ModelComputationContextBase, node: A return nodes let langLanguage* = newLanguage(IdLangLanguage, @[ + langRootClass, langAspectClass, roleDescriptorInterface, propertyTypeClass, propertyTypeBoolClass, propertyTypeStringClass, propertyTypeNumberClass, propertyDefinitionClass, classDefinitionClass, classReferenceClass, roleReferenceClass, referenceDefinitionClass, childrenDefinitionClass, @@ -314,13 +344,23 @@ let langLanguage* = newLanguage(IdLangLanguage, @[ proc createNodeClassFromLangDefinition*(def: AstNode): Option[NodeClass] = log lvlInfo, fmt"createNodeClassFromLangDefinition {def.dump(recurse=true)}" let name = def.property(IdINamedName).get.stringValue - let alias = "todo" - let canBeRoot = true # todo + let alias = def.property(IdClassDefinitionAlias).get.stringValue + + let isAbstract = def.property(IdClassDefinitionAbstract).get.boolValue + let isInterface = def.property(IdClassDefinitionInterface).get.boolValue + let isFinal = def.property(IdClassDefinitionFinal).get.boolValue + let canBeRoot = def.property(IdClassDefinitionCanBeRoot).get.boolValue + let precedence = def.property(IdClassDefinitionPrecedence).get.intValue var properties = newSeqOfCap[PropertyDescription](def.childCount(IdClassDefinitionProperties)) var references = newSeqOfCap[NodeReferenceDescription](def.childCount(IdClassDefinitionReferences)) var childDescriptions = newSeqOfCap[NodeChildDescription](def.childCount(IdClassDefinitionChildren)) + let substitutionProperty = if def.firstChild(IdClassDefinitionSubstitutionProperty).getSome(substitutionProperty): + substitutionProperty.reference(IdRoleReferenceTarget).RoleId.some + else: + RoleId.none + for _, prop in def.children(IdClassDefinitionProperties): let propName = prop.property(IdINamedName).get.stringValue let typ = if prop.firstChild(IdPropertyDefinitionType).getSome(typ): @@ -387,9 +427,94 @@ proc createNodeClassFromLangDefinition*(def: AstNode): Option[NodeClass] = childDescriptions.add NodeChildDescription(id: children.id.RoleId, role: childrenName, class: class, count: count) + let baseClass: NodeClass = nil + # use node id of the class definition node as class id - let class = newNodeClass(def.id.ClassId, name, alias=alias, interfaces=[], canBeRoot=canBeRoot, properties=properties, references=references, children=childDescriptions) + let class = newNodeClass(def.id.ClassId, name, alias=alias, base=baseClass, interfaces=[], + isAbstract=isAbstract, isInterface=isInterface, isFinal=isFinal, canBeRoot=canBeRoot, + substitutionProperty=substitutionProperty, precedence=precedence, + properties=properties, references=references, children=childDescriptions) # debugf"{class}" print class - return class.some \ No newline at end of file + return class.some + +proc createNodeFromNodeClass(classes: var Table[ClassId, AstNode], class: NodeClass): AstNode = + # log lvlInfo, fmt"createNodeFromNodeClass {class.name}" + + result = newAstNode(classDefinitionClass, class.id.NodeId.some) + # classes[class.id] = result + + result.setProperty(IdINamedName, PropertyValue(kind: String, stringValue: class.name)) + result.setProperty(IdClassDefinitionAlias, PropertyValue(kind: String, stringValue: class.alias)) + + result.setProperty(IdClassDefinitionAbstract, PropertyValue(kind: Bool, boolValue: class.isAbstract)) + result.setProperty(IdClassDefinitionInterface, PropertyValue(kind: Bool, boolValue: class.isInterface)) + result.setProperty(IdClassDefinitionFinal, PropertyValue(kind: Bool, boolValue: class.isFinal)) + result.setProperty(IdClassDefinitionCanBeRoot, PropertyValue(kind: Bool, boolValue: class.canBeRoot)) + result.setProperty(IdClassDefinitionPrecedence, PropertyValue(kind: Int, intValue: class.precedence)) + + if class.substitutionProperty.getSome(property): + var roleReference = newAstNode(roleReferenceClass) + roleReference.setReference(IdRoleReferenceTarget, property.NodeId) + result.add(IdClassDefinitionSubstitutionProperty, roleReference) + + for property in class.properties: + var propertyNode = newAstNode(propertyDefinitionClass, property.id.NodeId.some) + propertyNode.setProperty(IdINamedName, PropertyValue(kind: String, stringValue: property.role)) + + let propertyTypeClass = if property.typ == Int: + propertyTypeNumberClass + elif property.typ == String: + propertyTypeStringClass + elif property.typ == Bool: + propertyTypeBoolClass + else: + log lvlError, fmt"Invalid property type specified for {property}" + return nil + + propertyNode.add(IdPropertyDefinitionType, newAstNode(propertyTypeClass)) + result.add(IdClassDefinitionProperties, propertyNode) + + for reference in class.references: + var referenceNode = newAstNode(referenceDefinitionClass, reference.id.NodeId.some) + referenceNode.setProperty(IdINamedName, PropertyValue(kind: String, stringValue: reference.role)) + + let classReference = newAstNode(classReferenceClass) + classReference.setReference(IdClassReferenceTarget, reference.class.NodeId) + referenceNode.add(IdReferenceDefinitionClass, classReference) + + result.add(IdClassDefinitionReferences, referenceNode) + + for children in class.children: + var childrenNode = newAstNode(childrenDefinitionClass, children.id.NodeId.some) + childrenNode.setProperty(IdINamedName, PropertyValue(kind: String, stringValue: children.role)) + + let classReference = newAstNode(classReferenceClass) + classReference.setReference(IdClassReferenceTarget, children.class.NodeId) + childrenNode.add(IdChildrenDefinitionClass, classReference) + + let childrenCountClass = if children.count == ChildCount.ZeroOrOne: + countZeroOrOneClass + elif children.count == ChildCount.One: + countOneClass + elif children.count == ChildCount.ZeroOrMore: + countZeroOrMoreClass + elif children.count == ChildCount.OneOrMore: + countOneOrMoreClass + else: + log lvlError, fmt"Invalid child count specified for {children}" + return nil + + childrenNode.add(IdChildrenDefinitionCount, newAstNode(childrenCountClass)) + + result.add(IdClassDefinitionChildren, childrenNode) + + # debugf"node {result.dump(recurse=true)}" + +proc createNodesForLanguage*(language: Language): AstNode = + result = newAstNode(langRootClass) + + var classes = initTable[ClassId, AstNode]() + for class in language.classes.values: + result.add IdLangRootChildren, createNodeFromNodeClass(classes, class) \ No newline at end of file diff --git a/src/ast_ids.nim b/src/ast_ids.nim index 87100704..acec2c70 100644 --- a/src/ast_ids.nim +++ b/src/ast_ids.nim @@ -158,6 +158,11 @@ let IdGenericTypeValue* = "654fbb281446e19b3822521b".parseId.RoleId # lang language let IdLangLanguage* = "654fbb281446e19b3822523f".parseId.LanguageId +let IdLangRoot* = "654fbb281446e19b3822524f".parseId.ClassId +let IdLangRootChildren* = "654fbb281446e19b38225250".parseId.RoleId + +let IdLangAspect* = "654fbb281446e19b38225251".parseId.ClassId + let IdClassDefinition* = "654fbb281446e19b3822522a".parseId.ClassId let IdClassDefinitionAbstract* = "654fbb281446e19b38225236".parseId.RoleId let IdClassDefinitionInterface* = "654fbb281446e19b38225239".parseId.RoleId @@ -205,9 +210,6 @@ let IdIRoleDescriptor* = "654fbb281446e19b3822524c".parseId.ClassId # new ids -let Id654fbb281446e19b3822524f* = "654fbb281446e19b3822524f".parseId -let Id654fbb281446e19b38225250* = "654fbb281446e19b38225250".parseId -let Id654fbb281446e19b38225251* = "654fbb281446e19b38225251".parseId let Id654fbb281446e19b38225252* = "654fbb281446e19b38225252".parseId let Id654fbb281446e19b38225253* = "654fbb281446e19b38225253".parseId let Id654fbb281446e19b38225254* = "654fbb281446e19b38225254".parseId @@ -226,7 +228,6 @@ let Id654fbb281446e19b38225260* = "654fbb281446e19b38225260".parseId let Id654fbb281446e19b38225261* = "654fbb281446e19b38225261".parseId let Id654fbb281446e19b38225262* = "654fbb281446e19b38225262".parseId let Id654fbb281446e19b38225263* = "654fbb281446e19b38225263".parseId -let Id654fbb281446e19b38225264* = "654fbb281446e19b38225264".parseId # import strformat # for i in 0..100: diff --git a/src/model_document.nim b/src/model_document.nim index dc44cebf..e6d3a400 100644 --- a/src/model_document.nim +++ b/src/model_document.nim @@ -3016,9 +3016,10 @@ proc compileLanguage*(self: ModelDocumentEditor) {.expose("editor.model").} = return for root in self.document.model.rootNodes: - if root.class == IdClassDefinition: - let class = createNodeClassFromLangDefinition(root) - # todo + for _, child in root.children(IdLangRootChildren): + if child.class == IdClassDefinition: + let class = createNodeClassFromLangDefinition(child) + # todo proc addRootNode*(self: ModelDocumentEditor) {.expose("editor.model").} = var popup = self.app.createSelectorPopup().SelectorPopup @@ -3056,6 +3057,41 @@ proc saveProject*(self: ModelDocumentEditor) {.expose("editor.model").} = else: log lvlError, fmt"Failed to save project: no workspace" +proc loadBaseLanguageModel*(self: ModelDocumentEditor) {.expose("editor.model").} = + log lvlInfo, fmt"Loading base language model" + try: + var model = newModel() + var root = createNodesForLanguage(base_language.baseLanguage) + model.addLanguage(lang_language.langLanguage) + model.addRootNode(root) + + let oldModel = self.document.model + self.document.model = model + + discard self.document.model.onNodeDeleted.subscribe proc(d: auto) = self.document.handleNodeDeleted(d[0], d[1], d[2], d[3], d[4]) + discard self.document.model.onNodeInserted.subscribe proc(d: auto) = self.document.handleNodeInserted(d[0], d[1], d[2], d[3], d[4]) + discard self.document.model.onNodePropertyChanged.subscribe proc(d: auto) = self.document.handleNodePropertyChanged(d[0], d[1], d[2], d[3], d[4], d[5]) + discard self.document.model.onNodeReferenceChanged.subscribe proc(d: auto) = self.document.handleNodeReferenceChanged(d[0], d[1], d[2], d[3], d[4]) + + self.document.builder.clear() + for language in self.document.model.languages: + self.document.builder.addBuilder(language.builder) + + self.document.undoList.setLen 0 + self.document.redoList.setLen 0 + + functionInstances.clear() + self.document.ctx.state.clearCache() + + self.document.ctx.state.removeModel(oldModel) + self.document.ctx.state.addModel(model) + + except CatchableError: + log lvlError, fmt"Failed to load model source file '{self.document.filename}': {getCurrentExceptionMsg()}" + log lvlError, getCurrentException().getStackTrace() + + self.document.onModelChanged.invoke (self.document) + genDispatcher("editor.model") addActiveDispatchTable "editor.model", genDispatchTable("editor.model")