diff options
Diffstat (limited to 'compiler/enumtostr.nim')
-rw-r--r-- | compiler/enumtostr.nim | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/compiler/enumtostr.nim b/compiler/enumtostr.nim new file mode 100644 index 000000000..dc516d2e5 --- /dev/null +++ b/compiler/enumtostr.nim @@ -0,0 +1,110 @@ + +import ast, idents, lineinfos, modulegraphs, magicsys + +when defined(nimPreviewSlimSystem): + import std/assertions + + +proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph; idgen: IdGenerator): PSym = + result = newSym(skProc, getIdent(g.cache, "$"), idgen, t.owner, info) + + let dest = newSym(skParam, getIdent(g.cache, "e"), idgen, result, info) + dest.typ = t + + let res = newSym(skResult, getIdent(g.cache, "result"), idgen, result, info) + res.typ = getSysType(g, info, tyString) + + result.typ = newType(tyProc, idgen, t.owner) + result.typ.n = newNodeI(nkFormalParams, info) + rawAddSon(result.typ, res.typ) + result.typ.n.add newNodeI(nkEffectList, info) + + result.typ.addParam dest + + var body = newNodeI(nkStmtList, info) + var caseStmt = newNodeI(nkCaseStmt, info) + caseStmt.add(newSymNode dest) + + # copy the branches over, but replace the fields with the for loop body: + for i in 0..<t.n.len: + assert(t.n[i].kind == nkSym) + var field = t.n[i].sym + let val = if field.ast == nil: field.name.s else: field.ast.strVal + caseStmt.add newTree(nkOfBranch, newIntTypeNode(field.position, t), + newTree(nkStmtList, newTree(nkFastAsgn, newSymNode(res), newStrNode(val, info)))) + #newIntTypeNode(nkIntLit, field.position, t) + + body.add(caseStmt) + + var n = newNodeI(nkProcDef, info, bodyPos+2) + for i in 0..<n.len: n[i] = newNodeI(nkEmpty, info) + n[namePos] = newSymNode(result) + n[paramsPos] = result.typ.n + n[bodyPos] = body + n[resultPos] = newSymNode(res) + result.ast = n + incl result.flags, sfFromGeneric + incl result.flags, sfNeverRaises + +proc searchObjCaseImpl(obj: PNode; field: PSym): PNode = + case obj.kind + of nkSym: + result = nil + of nkElse, nkOfBranch: + result = searchObjCaseImpl(obj.lastSon, field) + else: + if obj.kind == nkRecCase and obj[0].kind == nkSym and obj[0].sym == field: + result = obj + else: + result = nil + for x in obj: + result = searchObjCaseImpl(x, field) + if result != nil: break + +proc searchObjCase(t: PType; field: PSym): PNode = + result = searchObjCaseImpl(t.n, field) + if result == nil and t.baseClass != nil: + result = searchObjCase(t.baseClass.skipTypes({tyAlias, tyGenericInst, tyRef, tyPtr}), field) + doAssert result != nil + +proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGraph; idgen: IdGenerator): PSym = + result = newSym(skProc, getIdent(g.cache, "objDiscMapping"), idgen, t.owner, info) + + let dest = newSym(skParam, getIdent(g.cache, "e"), idgen, result, info) + dest.typ = field.typ + + let res = newSym(skResult, getIdent(g.cache, "result"), idgen, result, info) + res.typ = getSysType(g, info, tyUInt8) + + result.typ = newType(tyProc, idgen, t.owner) + result.typ.n = newNodeI(nkFormalParams, info) + rawAddSon(result.typ, res.typ) + result.typ.n.add newNodeI(nkEffectList, info) + + result.typ.addParam dest + + var body = newNodeI(nkStmtList, info) + var caseStmt = newNodeI(nkCaseStmt, info) + caseStmt.add(newSymNode dest) + + let subObj = searchObjCase(t, field) + for i in 1..<subObj.len: + let ofBranch = subObj[i] + var newBranch = newNodeI(ofBranch.kind, ofBranch.info) + for j in 0..<ofBranch.len-1: + newBranch.add ofBranch[j] + + newBranch.add newTree(nkStmtList, newTree(nkFastAsgn, newSymNode(res), newIntNode(nkInt8Lit, i))) + caseStmt.add newBranch + + body.add(caseStmt) + + var n = newNodeI(nkProcDef, info, bodyPos+2) + for i in 0..<n.len: n[i] = newNodeI(nkEmpty, info) + n[namePos] = newSymNode(result) + n[paramsPos] = result.typ.n + n[bodyPos] = body + n[resultPos] = newSymNode(res) + result.ast = n + incl result.flags, sfFromGeneric + incl result.flags, sfNeverRaises |