summary refs log tree commit diff stats
path: root/compiler/lowerings.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/lowerings.nim')
-rw-r--r--compiler/lowerings.nim43
1 files changed, 42 insertions, 1 deletions
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index e2afa4362..5b61a9cae 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -64,6 +64,22 @@ proc createObj*(owner: PSym, info: TLineInfo): PType =
   incl result.flags, tfFinal
   result.n = newNodeI(nkRecList, info)
 
+proc rawAddField*(obj: PType; field: PSym) =
+  assert field.kind == skField
+  field.position = sonsLen(obj.n)
+  addSon(obj.n, newSymNode(field))
+
+proc rawIndirectAccess*(a: PNode; field: PSym; info: TLineInfo): PNode = 
+  # returns a[].field as a node
+  assert field.kind == skField
+  var deref = newNodeI(nkHiddenDeref, info)
+  deref.typ = a.typ.skipTypes(abstractInst).sons[0]
+  addSon(deref, a)
+  result = newNodeI(nkDotExpr, info)
+  addSon(result, deref)
+  addSon(result, newSymNode(field))
+  result.typ = field.typ
+
 proc addField*(obj: PType; s: PSym) =
   # because of 'gensym' support, we have to mangle the name with its ID.
   # This is hacky but the clean solution is much more complex than it looks.
@@ -74,6 +90,16 @@ proc addField*(obj: PType; s: PSym) =
   field.position = sonsLen(obj.n)
   addSon(obj.n, newSymNode(field))
 
+proc addUniqueField*(obj: PType; s: PSym) =
+  let fieldName = getIdent(s.name.s & $s.id)
+  if lookupInRecord(obj.n, fieldName) == nil:
+    var field = newSym(skField, fieldName, s.owner, s.info)
+    let t = skipIntLit(s.typ)
+    field.typ = t
+    assert t.kind != tyStmt
+    field.position = sonsLen(obj.n)
+    addSon(obj.n, newSymNode(field))
+
 proc newDotExpr(obj, b: PSym): PNode =
   result = newNodeI(nkDotExpr, obj.info)
   let field = getSymFromList(obj.typ.n, getIdent(b.name.s & $b.id))
@@ -95,13 +121,28 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo): PNode =
     t = t.sons[0]
     if t == nil: break
     t = t.skipTypes(abstractInst)
-  assert field != nil, b
+  #if field == nil:
+  #  debug deref.typ
+  #  echo deref.typ.id
+  internalAssert field != nil
   addSon(deref, a)
   result = newNodeI(nkDotExpr, info)
   addSon(result, deref)
   addSon(result, newSymNode(field))
   result.typ = field.typ
 
+proc getFieldFromObj*(t: PType; v: PSym): PSym =
+  assert v.kind != skField
+  let fieldName = getIdent(v.name.s & $v.id)
+  var t = t
+  while true:
+    assert t.kind == tyObject
+    result = getSymFromList(t.n, fieldName)
+    if result != nil: break
+    t = t.sons[0]
+    if t == nil: break
+    t = t.skipTypes(abstractInst)
+
 proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode = 
   # returns a[].b as a node
   result = indirectAccess(a, b.name.s & $b.id, info)